https://gcc.gnu.org/g:1730426b8a5a0afca50f09157bbd97799a95e980
commit r16-5751-g1730426b8a5a0afca50f09157bbd97799a95e980 Author: Jose E. Marchesi <[email protected]> Date: Sat Nov 22 02:19:52 2025 +0100 a68: parser: pragmats infrastructure This patch adds the infrastructure for adding handlers for pragmats, along with some intial support for the "access Module" pragmat. Signed-off-by: Jose E. Marchesi <[email protected]> gcc/ChangeLog * algol68/a68-parser-pragmat.cc: New file. Diff: --- gcc/algol68/a68-parser-pragmat.cc | 202 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 202 insertions(+) diff --git a/gcc/algol68/a68-parser-pragmat.cc b/gcc/algol68/a68-parser-pragmat.cc new file mode 100644 index 000000000000..2407eaa1b721 --- /dev/null +++ b/gcc/algol68/a68-parser-pragmat.cc @@ -0,0 +1,202 @@ +/* Handling of compiler pragmats. + Copyright (C) 2025 Jose E. Marchesi. + + Written by Jose E. Marchesi. + + GCC 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, or (at your option) + any later version. + + GCC 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 GCC; see the file COPYING3. If not see + <http://www.gnu.org/licenses/>. */ + +#define INCLUDE_MEMORY +#include "config.h" +#include "system.h" +#include "coretypes.h" + +#include "a68.h" + +/* Utility macros useful for parsing pragmat contents. */ + +#define SKIP_WHITESPACES(P) \ + while (ISSPACE (*(P))) (P)++ + +#define PARSE_WORD(P,W) \ + do \ + { \ + (W) = (char *) alloca (strlen ((P))); \ + size_t i = 0; \ + while (ISALPHA (*(P))) \ + (W)[i++] = *((P)++); \ + (W)[i] = '\0'; \ + } while (0) + +/* Parse a string denotation and return its value in an allocated buffer in + *STR. It is up to the caller to dispose of the allocated memory. + + This function returns a pointer to the character following the string + denotation in P, or P in case of parse error. + + In case of parse error *STR is also set to NULL. */ + +const char * +parse_string_denotation (const char *p, char **str) +{ + const char *orig = p; + size_t i = 0; + char *s = (char *) xmalloc (2 * strlen (p)); + + if (*(p++) != '\"') + goto error; + while (*p != '\0' && *p != '\"') + { + if (*p == '\'' && *(p + 1) == '\"') + { + s[i++] = '\"'; + p += 2; + } + else + { + s[i++] = *p; + p++; + } + } + if (*p != '\"') + goto error; + + *str = s; + return p + 1; + error: + free (s); + *str = NULL; + return orig; +} + +/* PR access MODULE in "filename" PR */ + +const char * +handle_access_in_pragmat (NODE_T *p, const char *pragmat, size_t pos) +{ + const char *beginning = pragmat; + + SKIP_WHITESPACES (pragmat); + /* Parse module name. */ + char *module; + PARSE_WORD (pragmat, module); + if (*module == '\0') + { + a68_error (p, "invalid pragmat: expected module name after %<access%>"); + return NULL; + } + SKIP_WHITESPACES (pragmat); + /* Parse "in " */ + if (strncmp (pragmat, "in ", 3) != 0) + { + a68_error (p, "invalid pragmat: expected %<in%> after module name"); + return NULL; + } + pragmat += 3; + SKIP_WHITESPACES (pragmat); + /* Parse a string denotation. */ + char *filename; + pragmat = parse_string_denotation (pragmat, &filename); + if (filename == NULL) + { + size_t off = pos + pragmat - beginning; + char *found; + PARSE_WORD (pragmat, found); + a68_error_in_pragmat (p, off, + "in %<access%> pragmat, expected string, found Z", + found); + return NULL; + } + /* Add entry in the module files map. */ + const char **pmodule = A68_MODULE_FILES->get (module); + if (pmodule != NULL) + { + a68_error_in_pragmat (p, pos + pragmat - beginning, + "module Z cannot appear in multiple %<access%> pragmats", + module); + return NULL; + } + + SKIP_WHITESPACES (pragmat); + /* Skip closing PR or PRAGMAT. */ + if (NPRAGMAT_TYPE (p) == STYLE_I_PRAGMAT_SYMBOL) + pragmat += 2; + else + pragmat += 7; + + A68_MODULE_FILES->put (ggc_strdup (module), ggc_strdup (filename)); + free (filename); + return pragmat; +} + +/* Parse and action on a pragmat. */ + +void +handle_pragmat (NODE_T *p) +{ + const char *pragmat = NPRAGMAT (p); + if (pragmat != NULL + && (NPRAGMAT_TYPE (p) == STYLE_I_PRAGMAT_SYMBOL + || NPRAGMAT_TYPE (p) == BOLD_PRAGMAT_SYMBOL)) + { + /* Process pragmat commands. */ + do + { + SKIP_WHITESPACES (pragmat); + /* Skip PR or PRAGMAT. */ + if (NPRAGMAT_TYPE (p) == STYLE_I_PRAGMAT_SYMBOL) + pragmat += 2; + else + pragmat += 7; + SKIP_WHITESPACES (pragmat); + /* Get first word in pragmat and dispatch. */ + SKIP_WHITESPACES (pragmat); + char *word = (char *) alloca (strlen (pragmat)); + size_t i = 0; + while (ISALPHA (*pragmat) || *pragmat == '\n') + word[i++] = *(pragmat++); + word[i] = '\0'; + + if (strcmp (word, "access") == 0) + { + pragmat + = handle_access_in_pragmat (p, pragmat, pragmat - NPRAGMAT (p)); + if (pragmat == NULL) + break; + } + else if (strcmp (word, "include") == 0) + /* Include pragmats are handled in the scanner. */ + return; + else + { + a68_error_in_pragmat (p, pragmat - NPRAGMAT (p), + "unrecognized pragmat Z", word); + break; + } + } + while (*pragmat != '\0'); + } +} + +/* Entry point: handle all pragmats in the given parse tree. */ + +void +a68_handle_pragmats (NODE_T *p) +{ + for (; p != NO_NODE; FORWARD (p)) + { + a68_handle_pragmats (SUB (p)); + handle_pragmat (p); + } +}
