Mercurial > ~dholland > hg > ag > index.cgi
view anagram/agcore/bpu.cpp @ 21:1c9dac05d040
Add lint-style FALLTHROUGH annotations to fallthrough cases.
(in the parse engine and thus the output code)
Document this, because the old output causes warnings with gcc10.
author | David A. Holland |
---|---|
date | Mon, 13 Jun 2022 00:04:38 -0400 |
parents | 13d2b8934445 |
children |
line wrap: on
line source
/* * AnaGram, A System for Syntax Directed Programming * Copyright 1993-1999 Parsifal Software. All Rights Reserved. * See the file COPYING for license and usage terms. * * bpu.cpp - Utility routines for bpe3 */ #include <ctype.h> #include <stdarg.h> #include "port.h" #include "arrays.h" #include "bpe3.h" #include "bpu.h" #include "cd.h" #include "data.h" #include "dict.h" #include "engdef.h" #include "keyword.h" #include "myalloc.h" #include "q1glbl.h" #include "rule.h" #include "stacks.h" #include "symbol.h" #include "token.h" //#define INCLUDE_LOGGING #include "log.h" void template_string(const char *name, const char *tp, const char tc) { ics(); while (*tp) { char c = *tp++; if (c == tc) { ass(name); continue; } acs(c); } tss(); } AgString subs_template(const char *name, const char *tp, const char tc) { template_string(name, tp, tc); return buildAgString(); } unsigned find_token_number(const char *name) { return Symbol(name)->token_number; //return map_token_name[identify_string(name,tkn_dict)].token_number; } int find_completions(int s, const unsigned **q) { state_number_map *sp = &map_state_number[s]; const unsigned *p = lstptr(*sp, chain_completions); int n = sp->n_chain_completions; if (n == 0 && sp->chain_gotos_index == 0) { p = lstptr(*sp, completions); n = sp->n_completions; } *q = p; return n; } void select_actions(int k) { int n = tis()/3; int *lb; list_space(n+1); lb = list_base; iws(); while (n--) { aws(lb[k]); k += 3; } } void find_key_tokens(const int *pl, int n, int tw /*, int ct */) { LOGSECTION("find_key_tokens"); LOGV(n); for (; n--; pl += tw) { //int tn = *pl; Token token = *pl; LOGV(token); //if (map_token_number[tn].key == 0) continue; //if (token->key == 0) continue; if (token->key.isNull()) { continue; } isws(token); } } /* * Note that the text of the defined format must not contain a newline. * Failure to abide by this rule will cause the line count to be * incorrect. */ void define_macro(const char *n, const char *fmt, ...) { va_list ap; fprintf(pe_file, "#define %s ", n); va_start(ap, fmt); vfprintf(pe_file, fmt, ap); va_end(ap); fputc('\n', pe_file); pe_line_count++; } void define_macro_default(const char *n, const char *fmt, ...) { va_list ap; char name_only[80]; char *ptr; strcpy(name_only, n); ptr = strchr(name_only, '('); if (ptr != NULL) { *ptr = 0; } fprintf(pe_file, "#ifndef %s\n#define %s ", name_only, n); va_start(ap, fmt); vfprintf(pe_file, fmt, ap); va_end(ap); fprintf(pe_file, "\n#endif\n"); pe_line_count += 3; } unsigned char *key_string(int tn) { LOGSECTION("key_string"); Keyword key = map_token_number[tn].key; LOGV(tn) LCV(key) LCV(Keyword::count()); if (key.isNull()) { return NULL; } LOGV(key->string); return (unsigned char *) key->string.pointer(); } /* * Function: reducing_token * Arguments: * token number, tn * state number, sn * Returns: 0 if tn is _not_ a reducing token in the given state * Otherwise, returns the number of the rule it reduces. */ #if 0 /* no longer used */ unsigned reducing_token(unsigned tn, unsigned sn) { state_number_map *sp = &map_state_number[sn]; const unsigned *p; unsigned n = sp->n_reductions; /* number of reductions in this state */ if (n) { p = lstptr(*sp, reductions); while (n--) { if (*p++ == tn) { return *p; } p++; } return 0; } if (sp->n_completed_forms != 1) { return 0; } if (shift_token(tn, sn)) { return 0; } return *(lstptr(*sp,completed_forms)); } #endif /* 0 - no longer used */ Rule ruleReducedBy(Token token, unsigned sn) { state_number_map *sp = &map_state_number[sn]; const unsigned *p; unsigned n = sp->n_reductions; /* number of reductions in this state */ if (n) { p = lstptr(*sp, reductions); while (n--) { if (*p++ == (unsigned) token) { return *p; } p++; } return 0; } if (sp->n_completed_forms != 1) { // Exit if more than one completed rule return 0; } if (shift_token(token, sn)) { // Exit if there's a shift return 0; } // Default reduction, return rule # return *(lstptr(*sp, completed_forms)); } void select_write_fragment(const char *name, const char *modes, const char *suffix) { char fragment[80]; strcpy(fragment, name); strcat(fragment, modes); strcat(fragment, suffix); write_code_segment(fragment); } int shift_token(unsigned tn, unsigned sn) { const unsigned *p; unsigned n; n = find_gotos(sn, &p); while (n--) { if (*p == tn) { return 1; } else { p += 2; } } n = find_completions(sn, &p); while (n--) { if (*p == tn) { return 1; } else { p += 2; } } return 0; } void count_pe_line(const char *s, int k) { LOGSECTION("count_pe_line"); while (k--) { if (s[k] == '\n') { pe_line_count++; } } LOGV(pe_line_count); } int wps(const char *s) { LOGSECTION("wps"); int k = strlen(s); fputs(s, pe_file); count_pe_line(s, k); return k; } int wss(void) { count_pe_line(string_base, tis()); fputs(string_base, pe_file); return rcs(); } int wpe(const char *fs, ...) { LOGSECTION("wpe"); va_list ap; char buf[2000]; va_start(ap, fs); vsprintf(buf, fs, ap); va_end(ap); return wps(buf); } void write_code_segment(const char *name) { LOGSECTION("write_code_segment"); LOGV(name); if (name == NULL) { return; } AgString text = code_segment(name); if (!text.exists()) { return; } char *buf = text.pointer(); wps(buf); wps("\n\n"); } static AgString expand_my_macros(const char *s) { LOGSECTION("expand_my_macros"); char *p; int col_no = 0, lb = 0, k; LOGV(s); if (my_macros == NULL) { return AgString(s); } ics(); while (*s) { char *word; int index; while (*s && !isalpha(*s) && *s != '_') { if (*s == '\n') { acs(*s++); col_no = 0; while (*s && *s == ' ') { col_no++, s++; } lb = col_no; continue; } if (lb == col_no) { for (k = lb; k--; ) { acs(' '); } } col_no++; acs(*s++); } if (*s == 0) { break; } ics(); while (*s && (isalpha(*s) || *s == '_')) { acs(*s++); } word = build_string(); index = identify_string(word, my_macros); if (index == 0) { if (lb == col_no) { for (k = lb; k--; ) { acs(' '); } } col_no += strlen(word); ass(word); DEALLOCATE(word); continue; } DEALLOCATE(word); p = my_macros_subs[index]; if (*p == 0 && lb == col_no && (*s == '\n' || strncmp(s,"\\\n",2) == 0)) { if (*s == '\\') { s++; } s++; col_no = 0; while (*s && *s == ' ') { col_no++; s++; } lb = col_no; continue; } if (lb == col_no) for (k = lb; k--;) acs(' '); for (; *p; p++ ) { acs(*p); col_no++; if (*p == '\n') { for (k = lb; k--; ) { acs(' '); } col_no = lb; continue; } } if (*s == '#') { s++; } } LOGV(string_base); return buildAgString(); } AgString code_segment(const char *name) { LOGSECTION("code_segment"); const char *rawtext = engdef_get(name); LOGV(rawtext); AgString mx = expand_my_macros(rawtext); LOGV(mx); return mx; }