Mercurial > repo
view interps/cfunge/cfunge-src/src/fingerprints/manager.c @ 12518:2d8fe55c6e65 draft default tip
<int-e> learn The password of the month is release incident pilot.
author | HackEso <hackeso@esolangs.org> |
---|---|
date | Sun, 03 Nov 2024 00:31:02 +0000 |
parents | 859f9b4339e6 |
children |
line wrap: on
line source
/* -*- mode: C; coding: utf-8; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- * * cfunge - A standard-conforming Befunge93/98/109 interpreter in C. * Copyright (C) 2008-2009 Arvid Norlander <anmaster AT tele2 DOT se> * * 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 the proxy's option) any later version. Arvid Norlander is a * proxy who can decide which future versions of the GNU General Public * License can be used. * * 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 <http://www.gnu.org/licenses/>. */ #include "../global.h" #include "manager.h" #include "../ip.h" #include "../settings.h" #include "../diagnostic.h" #include <assert.h> #include <limits.h> /* CHAR_BIT */ #include <stdbool.h> #include <stdio.h> #include <stdlib.h> /* exit */ #include <string.h> /* memcpy, strlen */ #define ALLOCCHUNKSIZE 2 #define MANAGER_INTERNAL #include "fingerprints.h" /// To get size of the fingerprint array #define FPRINT_ARRAY_SIZE sizeof(ImplementedFingerprints) / sizeof(ImplementedFingerprintEntry) /************************** * Opcode Stack functions * **************************/ #ifdef CONCURRENT_FUNGE /** * Duplicate an opcode stack, used for split (t). */ FUNGE_ATTR_FAST FUNGE_ATTR_NONNULL static inline void opcode_stack_duplicate(const fungeOpcodeStack * restrict old, fungeOpcodeStack * restrict new) { if (old->top) { new->entries = (fingerprintOpcode*)cf_malloc((old->top + 1) * sizeof(fingerprintOpcode)); if (FUNGE_UNLIKELY(!new->entries)) { DIAG_OOM("Couldn't allocate for fingerprint stack"); } new->size = old->top + 1; new->top = old->top; // Copy the pointers. memcpy(new->entries, old->entries, new->top * sizeof(fingerprintOpcode)); } else { new->entries = NULL; new->top = 0; new->size = 0; } } #endif /// Add an entry to an opcode stack. FUNGE_ATTR_FAST FUNGE_ATTR_NONNULL FUNGE_ATTR_WARN_UNUSED bool opcode_stack_push(instructionPointer * restrict ip, unsigned char opcode, fingerprintOpcode func) { fungeOpcodeStack * stack = &ip->fingerOpcodes[opcode - 'A']; // Check if we need to realloc. It may also be that stack->entries is NULL // (both stack->top and stack->size are 0 then. if (stack->top == stack->size) { fingerprintOpcode* newstack = cf_realloc(stack->entries, (stack->size + ALLOCCHUNKSIZE) * sizeof(fingerprintOpcode)); if (FUNGE_UNLIKELY(!newstack)) return false; stack->entries = newstack; stack->entries[stack->top] = func; stack->top++; stack->size += ALLOCCHUNKSIZE; } else { stack->entries[stack->top] = func; stack->top++; } return true; } FUNGE_ATTR_FAST FUNGE_ATTR_NONNULL fingerprintOpcode opcode_stack_pop(instructionPointer * restrict ip, unsigned char opcode) { fungeOpcodeStack * stack = &ip->fingerOpcodes[opcode - 'A']; if (stack->top == 0) { return NULL; } else { return stack->entries[--stack->top]; } } /** * Pop a function pointer from an opcode stack, discarding it. */ FUNGE_ATTR_FAST FUNGE_ATTR_NONNULL static inline void opcode_stack_drop(fungeOpcodeStack * restrict stack) { if (stack->top == 0) { return; } else { stack->top--; } } /**************************** * Opcode Manager functions * ****************************/ /// Clean up the fingerprint stacks for an IP. FUNGE_ATTR_FAST void manager_free(instructionPointer * restrict ip) { if (FUNGE_UNLIKELY(!ip)) return; for (int i = 0; i < FINGEROPCODECOUNT; i++) { cf_free(ip->fingerOpcodes[i].entries); } } #ifdef CONCURRENT_FUNGE /// Duplicate the opcode stacks from one ip to another, for concurrent Funge. FUNGE_ATTR_FAST void manager_duplicate(const instructionPointer * restrict oldip, instructionPointer * restrict newip) { for (int i = 0; i < FINGEROPCODECOUNT; i++) { opcode_stack_duplicate(&oldip->fingerOpcodes[i], &newip->fingerOpcodes[i]); } } #endif #define FPRINT_NOTFOUND -1 /** * Return value is index into ImplementedFingerprints array. * -1 means not found. */ FUNGE_ATTR_FAST FUNGE_ATTR_WARN_UNUSED static inline ssize_t find_fingerprint(const funge_cell fingerprint) { for (size_t i = 0; i < FPRINT_ARRAY_SIZE; i++) { if (fingerprint <= ImplementedFingerprints[i].fprint) { // Then it is larger... as in "not found" if (fingerprint != ImplementedFingerprints[i].fprint) return FPRINT_NOTFOUND; // If we run in a sandbox, can fingerprint be loaded? // If not: break, as we know we found the right fingerprint, // so no need to search more. if (setting_enable_sandbox && !ImplementedFingerprints[i].safe) return FPRINT_NOTFOUND; return (ssize_t)i; } } return FPRINT_NOTFOUND; } FUNGE_ATTR_FAST bool manager_load(instructionPointer * restrict ip, funge_cell fingerprint) { ssize_t index = find_fingerprint(fingerprint); if (index == FPRINT_NOTFOUND) { return false; } else { bool gotLoaded = ImplementedFingerprints[index].loader(ip); if (FUNGE_LIKELY(gotLoaded)) { stack_push(ip->stack, fingerprint); stack_push(ip->stack, 1); return true; } else { return false; } } } FUNGE_ATTR_FAST bool manager_unload(instructionPointer * restrict ip, funge_cell fingerprint) { ssize_t index = find_fingerprint(fingerprint); if (index == FPRINT_NOTFOUND) return false; for (size_t i = 0; i < strlen(ImplementedFingerprints[index].opcodes); i++) opcode_stack_drop(&ip->fingerOpcodes[ImplementedFingerprints[index].opcodes[i] - 'A']); return true; } #if CHAR_BIT != 8 # error "CHAR_BIT != 8, please make sure the function below the location of this error works on your system." #endif FUNGE_ATTR_FAST FUNGE_ATTR_COLD FUNGE_ATTR_NORET void manager_list(void) { puts("Supported fingerprints in this binary:"); for (size_t i = 0; i < FPRINT_ARRAY_SIZE; i++) { // This hack is here to reconstruct the name from the fingerprint. // It will probably break if char isn't 8 bits. funge_cell fprint = ImplementedFingerprints[i].fprint; char fprintname[5] = { (char)(fprint >> 24), (char)(fprint >> 16), (char)(fprint >> 8), (char)fprint, '\0' }; printf("0x%x %s%s %s\n", (unsigned)fprint, fprintname, ImplementedFingerprints[i].safe ? "" : " (not available in sandbox mode)", ImplementedFingerprints[i].url ? ImplementedFingerprints[i].url : ""); } exit(0); }