📄 ghwlib.c
字号:
/* GHDL Wavefile reader library. Copyright (C) 2005 Tristan Gingold GHDL 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 2, or (at your option) any later version. GHDL 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 COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.*/#include <stdio.h>#include <stdint.h>#include <string.h>#include <stdlib.h>#include <unistd.h>#include "ghwlib.h"intghw_open (struct ghw_handler *h, const char *filename){ char hdr[16]; h->stream = fopen (filename, "rb"); if (h->stream == NULL) return -1; if (fread (hdr, sizeof (hdr), 1, h->stream) != 1) return -1; /* Check magic. */ if (memcmp (hdr, "GHDLwave\n", 9) != 0) return -2; /* Check version. */ if (hdr[9] != 16 || hdr[10] != 0) return -2; h->version = hdr[11]; if (h->version > 1) return -3; if (hdr[12] == 1) h->word_be = 0; else if (hdr[12] == 2) h->word_be = 1; else return -4;#if 0 /* Endianness. */ { int endian; union { unsigned char b[4]; uint32_t i;} v; v.i = 0x11223344; if (v.b[0] == 0x11) endian = 2; else if (v.b[0] == 0x44) endian = 1; else return -3; if (hdr[12] != 1 && hdr[12] != 2) return -3; if (hdr[12] != endian) h->swap_word = 1; else h->swap_word = 0; }#endif h->word_len = hdr[13]; h->off_len = hdr[14]; if (hdr[15] != 0) return -5; h->hie = NULL; return 0;}int32_tghw_get_i32 (struct ghw_handler *h, unsigned char *b){ if (h->word_be) return (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | (b[3] << 0); else return (b[3] << 24) | (b[2] << 16) | (b[1] << 8) | (b[0] << 0);}int64_tghw_get_i64 (struct ghw_handler *ghw_h, unsigned char *b){ int l, h; if (ghw_h->word_be) { h = (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | (b[3] << 0); l = (b[4] << 24) | (b[5] << 16) | (b[6] << 8) | (b[7] << 0); } else { l = (b[3] << 24) | (b[2] << 16) | (b[1] << 8) | (b[0] << 0); h = (b[7] << 24) | (b[6] << 16) | (b[5] << 8) | (b[4] << 0); } return (((int64_t)h) << 32) | l;}intghw_read_byte (struct ghw_handler *h, unsigned char *res){ int v; v = fgetc (h->stream); if (v == EOF) return -1; *res = v; return 0;}intghw_read_uleb128 (struct ghw_handler *h, uint32_t *res){ unsigned int r = 0; unsigned int off = 0; while (1) { int v = fgetc (h->stream); if (v == EOF) return -1; r |= (v & 0x7f) << off; if ((v & 0x80) == 0) break; off += 7; } *res = r; return 0;}intghw_read_sleb128 (struct ghw_handler *h, int32_t *res){ int32_t r = 0; unsigned int off = 0; while (1) { int v = fgetc (h->stream); if (v == EOF) return -1; r |= ((int32_t)(v & 0x7f)) << off; off += 7; if ((v & 0x80) == 0) { if ((v & 0x40) && off < 32) r |= -1 << off; break; } } *res = r; return 0;}intghw_read_lsleb128 (struct ghw_handler *h, int64_t *res){ int64_t r = 0; unsigned int off = 0; while (1) { int v = fgetc (h->stream); if (v == EOF) return -1; r |= ((int64_t)(v & 0x7f)) << off; off += 7; if ((v & 0x80) == 0) { if ((v & 0x40) && off < 64) r |= __INT64_C (-1) << off; break; } } *res = r; return 0;}intghw_read_f64 (struct ghw_handler *h, double *res){ /* FIXME: handle byte order. */ if (fread (res, sizeof (*res), 1, h->stream) != 1) return -1; return 0;}const char *ghw_read_strid (struct ghw_handler *h){ unsigned int id; if (ghw_read_uleb128 (h, &id) != 0) return NULL; return h->str_table[id];}union ghw_type *ghw_read_typeid (struct ghw_handler *h){ unsigned int id; if (ghw_read_uleb128 (h, &id) != 0) return NULL; return h->types[id - 1];}union ghw_range *ghw_read_range (struct ghw_handler *h){ int t = fgetc (h->stream); if (t == EOF) return NULL; switch (t & 0x7f) { case ghdl_rtik_type_e8: { struct ghw_range_e8 *r; r = malloc (sizeof (struct ghw_range_e8)); r->kind = t & 0x7f; r->dir = (t & 0x80) != 0; if (ghw_read_byte (h, &r->left) != 0) return NULL; if (ghw_read_byte (h, &r->right) != 0) return NULL; return (union ghw_range *)r; } case ghdl_rtik_type_i32: case ghdl_rtik_type_p32: { struct ghw_range_i32 *r; r = malloc (sizeof (struct ghw_range_i32)); r->kind = t & 0x7f; r->dir = (t & 0x80) != 0; if (ghw_read_sleb128 (h, &r->left) != 0) return NULL; if (ghw_read_sleb128 (h, &r->right) != 0) return NULL; return (union ghw_range *)r; } case ghdl_rtik_type_i64: case ghdl_rtik_type_p64: { struct ghw_range_i64 *r; r = malloc (sizeof (struct ghw_range_i64)); r->kind = t & 0x7f; r->dir = (t & 0x80) != 0; if (ghw_read_lsleb128 (h, &r->left) != 0) return NULL; if (ghw_read_lsleb128 (h, &r->right) != 0) return NULL; return (union ghw_range *)r; } case ghdl_rtik_type_f64: { struct ghw_range_f64 *r; r = malloc (sizeof (struct ghw_range_f64)); r->kind = t & 0x7f; r->dir = (t & 0x80) != 0; if (ghw_read_f64 (h, &r->left) != 0) return NULL; if (ghw_read_f64 (h, &r->right) != 0) return NULL; return (union ghw_range *)r; } default: fprintf (stderr, "ghw_read_range: type %d unhandled\n", t & 0x7f); return NULL; }}intghw_read_str (struct ghw_handler *h){ char hdr[12]; int i; char *p; int prev_len; if (fread (hdr, sizeof (hdr), 1, h->stream) != 1) return -1; if (hdr[0] != 0 || hdr[1] != 0 || hdr[2] != 0 || hdr[3] != 0) return -1; h->nbr_str = ghw_get_i32 (h, &hdr[4]); h->nbr_str++; h->str_size = ghw_get_i32 (h, &hdr[8]); h->str_table = (char **)malloc ((h->nbr_str + 1) * sizeof (char *)); h->str_content = (char *)malloc (h->str_size + h->nbr_str + 1); if (h->flag_verbose) { printf ("Number of strings: %d\n", h->nbr_str - 1); printf ("String table size: %d\n", h->str_size); } h->str_table[0] = "<anon>"; p = h->str_content; prev_len = 0; for (i = 1; i < h->nbr_str; i++) { int j; int c; char *prev; int sh; h->str_table[i] = p; prev = h->str_table[i - 1]; for (j = 0; j < prev_len; j++) *p++ = prev[j]; while (1) { c = fgetc (h->stream); if (c == EOF) return -1; if ((c >= 0 && c <= 31) || (c >= 128 && c <= 159)) break; *p++ = c; } *p++ = 0; if (h->flag_verbose > 1) printf ("string %d (pl=%d): %s\n", i, prev_len, h->str_table[i]); prev_len = c & 0x1f; sh = 5; while (c >= 128) { c = fgetc (h->stream); if (c == EOF) return -1; prev_len |= (c & 0x1f) << sh; sh += 5; } } if (fread (hdr, 4, 1, h->stream) != 1) return -1; if (memcmp (hdr, "EOS", 4) != 0) return -1; return 0;}union ghw_type *ghw_get_base_type (union ghw_type *t){ switch (t->kind) { case ghdl_rtik_type_b2: case ghdl_rtik_type_e8: case ghdl_rtik_type_e32: case ghdl_rtik_type_i32: case ghdl_rtik_type_i64: case ghdl_rtik_type_f64: case ghdl_rtik_type_p32: case ghdl_rtik_type_p64: return t; case ghdl_rtik_subtype_scalar: return t->ss.base; case ghdl_rtik_subtype_array: return (union ghw_type*)(t->sa.base); default: fprintf (stderr, "ghw_get_base_type: cannot handle type %d\n", t->kind); abort (); }}intget_nbr_elements (union ghw_type *t){ switch (t->kind) { case ghdl_rtik_type_b2: case ghdl_rtik_type_e8: case ghdl_rtik_type_e32: case ghdl_rtik_type_i32: case ghdl_rtik_type_i64: case ghdl_rtik_type_f64: case ghdl_rtik_type_p32: case ghdl_rtik_type_p64: case ghdl_rtik_subtype_scalar: return 1; case ghdl_rtik_subtype_array: case ghdl_rtik_subtype_array_ptr: return t->sa.nbr_el; case ghdl_rtik_type_record: return t->rec.nbr_el; default: fprintf (stderr, "get_nbr_elements: unhandled type %d\n", t->kind); abort (); }}intget_range_length (union ghw_range *rng){ switch (rng->kind) { case ghdl_rtik_type_i32: if (rng->i32.dir) return (rng->i32.left - rng->i32.right + 1); else return (rng->i32.right - rng->i32.left + 1); default: fprintf (stderr, "get_range_length: unhandled kind %d\n", rng->kind); abort (); }}intghw_read_type (struct ghw_handler *h){ char hdr[8]; int i; if (fread (hdr, sizeof (hdr), 1, h->stream) != 1) return -1; if (hdr[0] != 0 || hdr[1] != 0 || hdr[2] != 0 || hdr[3] != 0) return -1; h->nbr_types = ghw_get_i32 (h, &hdr[4]); h->types = (union ghw_type **) malloc (h->nbr_types * sizeof (union ghw_type *)); for (i = 0; i < h->nbr_types; i++) { int t; t = fgetc (h->stream); if (t == EOF) return -1; /* printf ("type[%d]= %d\n", i, t); */ switch (t) { case ghdl_rtik_type_b2: case ghdl_rtik_type_e8: { struct ghw_type_enum *e; int j; e = malloc (sizeof (struct ghw_type_enum)); e->kind = t; e->wkt = ghw_wkt_unknown; e->name = ghw_read_strid (h); if (ghw_read_uleb128 (h, &e->nbr) != 0) return -1; e->lits = (const char **) malloc (e->nbr * sizeof (char *)); if (h->flag_verbose > 1) printf ("enum %s:", e->name); for (j = 0; j < e->nbr; j++) { e->lits[j] = ghw_read_strid (h); if (h->flag_verbose > 1) printf (" %s", e->lits[j]); } if (h->flag_verbose > 1) printf ("\n"); h->types[i] = (union ghw_type *)e; } break; case ghdl_rtik_type_i32: case ghdl_rtik_type_i64: case ghdl_rtik_type_f64: { struct ghw_type_scalar *sc; sc = malloc (sizeof (struct ghw_type_scalar)); sc->kind = t; sc->name = ghw_read_strid (h); if (h->flag_verbose > 1) printf ("scalar: %s\n", sc->name); h->types[i] = (union ghw_type *)sc; } break; case ghdl_rtik_type_p32: case ghdl_rtik_type_p64: { struct ghw_type_physical *ph; ph = malloc (sizeof (struct ghw_type_physical)); ph->kind = t; ph->name = ghw_read_strid (h); if (h->version == 0) ph->nbr_units = 0; else { int i; if (ghw_read_uleb128 (h, &ph->nbr_units) != 0) return -1; ph->units = malloc (ph->nbr_units * sizeof (struct ghw_unit)); for (i = 0; i < ph->nbr_units; i++) { ph->units[i].name = ghw_read_strid (h); if (ghw_read_lsleb128 (h, &ph->units[i].val) < 0) return -1; } } if (h->flag_verbose > 1) printf ("physical: %s\n", ph->name); h->types[i] = (union ghw_type *)ph; } break; case ghdl_rtik_subtype_scalar: { struct ghw_subtype_scalar *ss; ss = malloc (sizeof (struct ghw_subtype_scalar)); ss->kind = t; ss->name = ghw_read_strid (h); ss->base = ghw_read_typeid (h); ss->rng = ghw_read_range (h); if (h->flag_verbose > 1) printf ("subtype scalar: %s\n", ss->name); h->types[i] = (union ghw_type *)ss; } break; case ghdl_rtik_type_array: { struct ghw_type_array *arr; int j; arr = malloc (sizeof (struct ghw_type_array)); arr->kind = t; arr->name = ghw_read_strid (h); arr->el = ghw_read_typeid (h); if (ghw_read_uleb128 (h, &arr->nbr_dim) != 0) return -1; arr->dims = (union ghw_type **) malloc (arr->nbr_dim * sizeof (union ghw_type *)); for (j = 0; j < arr->nbr_dim; j++) arr->dims[j] = ghw_read_typeid (h); if (h->flag_verbose > 1) printf ("array: %s\n", arr->name); h->types[i] = (union ghw_type *)arr; } break; case ghdl_rtik_subtype_array: case ghdl_rtik_subtype_array_ptr: { struct ghw_subtype_array *sa; int j; int nbr_el; sa = malloc (sizeof (struct ghw_subtype_array)); sa->kind = t; sa->name = ghw_read_strid (h); sa->base = (struct ghw_type_array *)ghw_read_typeid (h); nbr_el = get_nbr_elements (sa->base->el); sa->rngs = malloc (sa->base->nbr_dim * sizeof (union ghw_range *)); for (j = 0; j < sa->base->nbr_dim; j++) { sa->rngs[j] = ghw_read_range (h); nbr_el *= get_range_length (sa->rngs[j]); } sa->nbr_el = nbr_el; if (h->flag_verbose > 1) printf ("subtype array: %s (nbr_el=%d)\n", sa->name, sa->nbr_el); h->types[i] = (union ghw_type *)sa; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -