/* Copyright 2010-2023 Free Software Foundation, Inc. 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 "debug.h" #include "context_stack.h" #include "commands.h" #include "errors.h" static enum context *context_stack; static size_t top; /* One above last pushed context. */ static size_t space; /* Kept in sync with context_stack. */ static COMMAND_STACK command_stack; /* Generic command stack functions */ void reset_command_stack (COMMAND_STACK *stack) { stack->top = 0; stack->space = 0; free (stack->stack); stack->stack = 0; } void push_command (COMMAND_STACK *stack, enum command_id cmd) { if (stack->top >= stack->space) { stack->stack = realloc (stack->stack, (stack->space += 5) * sizeof (enum command_id)); } stack->stack[stack->top] = cmd; stack->top++; } enum command_id pop_command (COMMAND_STACK *stack) { if (stack->top == 0) fatal ("command stack empty"); return stack->stack[--stack->top]; } enum command_id top_command (COMMAND_STACK *stack) { if (stack->top == 0) fatal ("command stack empty for top"); return stack->stack[stack->top - 1]; } enum command_id current_context_command (void) { int i; if (top == 0) return CM_NONE; for (i = top -1; i >= 0; i--) { if (command_stack.stack[i] != CM_NONE) return command_stack.stack[i]; } return CM_NONE; } /* Context stacks */ void reset_context_stack (void) { top = 0; reset_command_stack (&command_stack); } char * context_name (enum context c) { return c == ct_preformatted ? "ct_preformatted" : c == ct_line ? "ct_line" : c == ct_def ? "ct_def" : c == ct_brace_command ? "ct_brace_command" : ""; } void push_context (enum context c, enum command_id cmd) { if (top >= space) context_stack = realloc (context_stack, (space += 5) * sizeof (enum context)); /* debug not in perl parser debug (">>>>>>>>>>>>>>>>>PUSHING STACK AT %d -- %s @%s", top, context_name (c), command_name(cmd)); */ context_stack[top] = c; top++; push_command (&command_stack, cmd); } enum context pop_context () { if (top == 0) fatal ("context stack empty"); (void) pop_command (&command_stack); /* debug not in perl parser debug (">>>>>>>>>>>>>POPPING STACK AT %d", top - 1); */ return context_stack[--top]; } enum context current_context (void) { if (top == 0) return ct_NONE; return context_stack[top - 1]; } int in_context (enum context context) { int i; if (top == 0) return 0; for (i = 0; i < top; i++) { if (context_stack[i] == context) return 1; } return 0; } /* Command nesting context. */ NESTING_CONTEXT nesting_context; /* used for @kbd */ int in_preformatted_context_not_menu() { int i; if (top == 0) return 0; for (i = top -1; i >= 0; i--) { enum context ct; enum command_id cmd; ct = context_stack[i]; if (ct != ct_line && ct != ct_preformatted) return 0; cmd = command_stack.stack[i]; if (command_data(cmd).flags & CF_block && command_data(cmd).data != BLOCK_menu && ct == ct_preformatted) return 1; } return 0; }