annotate keiko/util.c @ 0:bfdcc3820b32

Basis
author Mike Spivey <mike@cs.ox.ac.uk>
date Thu, 05 Oct 2017 08:04:15 +0100
parents
children
rev   line source
mike@0 1 /*
mike@0 2 * util.c
mike@0 3 *
mike@0 4 * This file is part of the Oxford Oberon-2 compiler
mike@0 5 * Copyright (c) 2006--2016 J. M. Spivey
mike@0 6 * All rights reserved
mike@0 7 *
mike@0 8 * Redistribution and use in source and binary forms, with or without
mike@0 9 * modification, are permitted provided that the following conditions are met:
mike@0 10 *
mike@0 11 * 1. Redistributions of source code must retain the above copyright notice,
mike@0 12 * this list of conditions and the following disclaimer.
mike@0 13 * 2. Redistributions in binary form must reproduce the above copyright notice,
mike@0 14 * this list of conditions and the following disclaimer in the documentation
mike@0 15 * and/or other materials provided with the distribution.
mike@0 16 * 3. The name of the author may not be used to endorse or promote products
mike@0 17 * derived from this software without specific prior written permission.
mike@0 18 *
mike@0 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
mike@0 20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
mike@0 21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
mike@0 22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
mike@0 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
mike@0 24 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
mike@0 25 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
mike@0 26 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
mike@0 27 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
mike@0 28 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
mike@0 29 */
mike@0 30
mike@0 31 #include "config.h"
mike@0 32 #include <stdio.h>
mike@0 33 #include <stdarg.h>
mike@0 34 #include <stdlib.h>
mike@0 35 #include <ctype.h>
mike@0 36 #include <string.h>
mike@0 37 #include "obcommon.h"
mike@0 38 #include "util.h"
mike@0 39 #include <assert.h>
mike@0 40
mike@0 41 EXTERN int dflag;
mike@0 42
mike@0 43 char *prog_name;
mike@0 44
mike@0 45 void error(const char *msg, ...) {
mike@0 46 va_list va;
mike@0 47
mike@0 48 va_start(va, msg);
mike@0 49 fprintf(stderr, "%s: ", err_file);
mike@0 50 vfprintf(stderr, msg, va);
mike@0 51 va_end(va);
mike@0 52 fprintf(stderr, "\n");
mike@0 53
mike@0 54 status = 1;
mike@0 55 }
mike@0 56
mike@0 57 void panic(const char *msg, ...) {
mike@0 58 va_list va;
mike@0 59 mybool bug = FALSE;
mike@0 60
mike@0 61 if (*msg == '*') {
mike@0 62 bug = TRUE; msg++;
mike@0 63 }
mike@0 64
mike@0 65 fprintf(stderr, "%s: Fatal error -- ", progname);
mike@0 66 va_start(va, msg);
mike@0 67 vfprintf(stderr, msg, va);
mike@0 68 va_end(va);
mike@0 69 if (err_file != NULL)
mike@0 70 fprintf(stderr, " in %s", err_file);
mike@0 71 fprintf(stderr, "\n");
mike@0 72 if (bug)
mike@0 73 fprintf(stderr, "Please report bugs to %s or %s\n",
mike@0 74 PACKAGE_TRACKER, PACKAGE_BUGREPORT);
mike@0 75
mike@0 76 exit(2);
mike@0 77 }
mike@0 78
mike@0 79 /* must_alloc -- malloc or die */
mike@0 80 void *must_alloc(int n, const char *why) {
mike@0 81 void *p;
mike@0 82 #ifdef DEBUG
mike@0 83 if (dflag >= 2) printf("Allocating %s as %d", why, n);
mike@0 84 #endif
mike@0 85 p = malloc(n);
mike@0 86 #ifdef DEBUG
mike@0 87 if (dflag >= 2) printf(" at %p\n", p);
mike@0 88 #endif
mike@0 89 if (p == NULL) panic("couldn't allocate space for %s", why);
mike@0 90 memset(p, 0, n);
mike@0 91 return p;
mike@0 92 }
mike@0 93
mike@0 94 /* must_strdup -- strdup or die */
mike@0 95 char *must_strdup(const char *s) {
mike@0 96 char *p = (char *) must_alloc(strlen(s)+1, s);
mike@0 97 strcpy(p, s);
mike@0 98 return p;
mike@0 99 }
mike@0 100
mike@0 101 /* must_realloc -- realloc or (you guessed it) */
mike@0 102 void *must_realloc(void *p, int n0, int n, const char *msg) {
mike@0 103 #ifdef DEBUG
mike@0 104 if (dflag >= 2) {
mike@0 105 printf("Growing %s at %p from %d to %d\n", msg, p, n0, n);
mike@0 106 fflush(stdout);
mike@0 107 }
mike@0 108 #endif
mike@0 109 p = realloc(p, n);
mike@0 110 if (p == NULL) panic("couldn't expand space for %s", msg);
mike@0 111 memset(((char *) p) + n0, 0, n-n0);
mike@0 112 return p;
mike@0 113 }
mike@0 114
mike@0 115 void _buf_init(struct _growbuf *b, int size, int margin,
mike@0 116 int elsize, const char *name) {
mike@0 117 b->buf = must_alloc(size * elsize, name);
mike@0 118 b->loc = 0;
mike@0 119 b->size = size;
mike@0 120 b->margin = margin;
mike@0 121 b->elsize = elsize;
mike@0 122 b->name = name;
mike@0 123 }
mike@0 124
mike@0 125 void _buf_grow(struct _growbuf *b) {
mike@0 126 if (b == NULL) panic("*uninitialized growbuf");
mike@0 127
mike@0 128 /* Ensure space for margin+1 items */
mike@0 129 if (b->loc > b->size - b->margin) {
mike@0 130 int size1 = max(b->size * GROW, b->loc + b->margin);
mike@0 131 b->buf = must_realloc(b->buf, b->size * b->elsize,
mike@0 132 size1 * b->elsize, b->name);
mike@0 133 b->size = size1;
mike@0 134 }
mike@0 135 }
mike@0 136
mike@0 137 #define SIZE 10
mike@0 138 #define PAGE 40000
mike@0 139
mike@0 140 void *pool_alloc(mempool *pool, int size) {
mike@0 141 void *result;
mike@0 142
mike@0 143 assert(size < PAGE);
mike@0 144
mike@0 145 if (pool->p_alloc + size > pool->p_pool[pool->p_current] + PAGE) {
mike@0 146 pool->p_current++;
mike@0 147 if (pool->p_current >= pool->p_npools) {
mike@0 148 if (pool->p_npools >= pool->p_size) {
mike@0 149 pool->p_pool = (unsigned char **)
mike@0 150 must_realloc(pool->p_pool,
mike@0 151 pool->p_size * sizeof(void *),
mike@0 152 2 * pool->p_size * sizeof(void *),
mike@0 153 "pool table");
mike@0 154 pool->p_size *= 2;
mike@0 155 }
mike@0 156 pool->p_pool[pool->p_npools++] =
mike@0 157 (uchar *) must_alloc(PAGE, "pools");
mike@0 158 }
mike@0 159 pool->p_alloc = pool->p_pool[pool->p_current];
mike@0 160 }
mike@0 161
mike@0 162 result = (void *) pool->p_alloc;
mike@0 163 pool->p_alloc += size;
mike@0 164 return result;
mike@0 165 }
mike@0 166
mike@0 167 void pool_reset(mempool *pool) {
mike@0 168 if (pool->p_pool == NULL) {
mike@0 169 pool->p_pool = (unsigned char **)
mike@0 170 must_alloc(SIZE * sizeof(void *), "pool table");
mike@0 171 pool->p_pool[0] = (uchar *) must_alloc(PAGE, "pools");
mike@0 172 pool->p_npools = 1; pool->p_size = SIZE;
mike@0 173 }
mike@0 174
mike@0 175 pool->p_current = 0;
mike@0 176 pool->p_alloc = pool->p_pool[0];
mike@0 177 }
mike@0 178
mike@0 179
mike@0 180 int split_line(char *line, char **words) {
mike@0 181 int nwords = 0;
mike@0 182 char *s;
mike@0 183
mike@0 184 s = line;
mike@0 185 while (*s == ' ' || *s == '\t' || *s == '\r') s++;
mike@0 186 if (*s == '\n' || *s == '!' || *s == '\0') return 0;
mike@0 187
mike@0 188 /* Set the words array */
mike@0 189 while (1) {
mike@0 190 while (*s == ' ' || *s == '\t' || *s == '\r') s++;
mike@0 191 if (*s == '\n' || *s == '\0') break;
mike@0 192 if (nwords == MAXWORDS) panic("too many words");
mike@0 193 words[nwords++] = s;
mike@0 194 while (! isspace((int) *s) && *s != '\0') s++;
mike@0 195 if (*s == '\n' || *s == '\0') { *s = '\0'; break; }
mike@0 196 *s++ = '\0';
mike@0 197 }
mike@0 198
mike@0 199 return nwords;
mike@0 200 }
mike@0 201
mike@0 202 /* squidge -- change Oberon-style name into C identifier */
mike@0 203 char *squidge(char *name) {
mike@0 204 static char buf[128];
mike@0 205 char *t = buf;
mike@0 206
mike@0 207 for (char *s = name; *s != '\0'; s++)
mike@0 208 *t++ = ((*s == '.' || *s == '%') ? '_' : *s);
mike@0 209 *t = '\0';
mike@0 210
mike@0 211 return buf;
mike@0 212 }