This is segment.c in view mode; [Download] [Up]
/* * Copyright (C) 1985-1992 New York University * * This file is part of the Ada/Ed-C system. See the Ada/Ed README file for * warranty (none) and distribution info and also the GNU General Public * License for more details. */ #define GEN #include "hdr.h" #include "vars.h" #include "gvars.h" #include "type.h" #include "segment.h" #include "miscprots.h" #include "dbxprots.h" #include "axqrprots.h" #include "gmiscprots.h" #include "segmentprots.h" static void segment_put_n(Segment, int, int, char *); static void segment_realloc(Segment, unsigned); extern Segment CODE_SEGMENT, DATA_SEGMENT, DATA_SEGMENT_MAIN; #ifdef MACHINE_CODE void print_data_segment() /*;print_data_segment*/ { Segment seg; char line[250], c; int i, w, *sp; seg = DATA_SEGMENT; sp = (int *) seg->seg_data; to_gen(" "); to_gen_int("--- Global data segment # ", CURRENT_DATA_SEGMENT); for (i = 0; i < seg->seg_maxpos; i++) { w = *sp++; if (w >= ' ' && w <= '~') c = w; else c = ' '; sprintf(line, " %5d %8x %c %d", i, w, c, w); to_gen(line); } } #endif void segment_append(Segment s, Segment sa) /*;segment_append*/ { /* append segment sa at end of segment s */ int i, la; seg_check(s); if (s->seg_kind != SEGMENT_KIND_DATA) chaos("segment_append not appending a data segment"); s->seg_pos = s->seg_maxpos; la = sa->seg_maxpos; for (i = 0; i < la; i++) { segment_put_int(s, ((int *)(sa->seg_data))[i]); } } void seg_check(Segment seg) /*;seg_check*/ { if (seg->seg_id != SEG_ID) chaos("invalid segment - check word invalid "); } void segment_empty(Segment s) /*;segment_empty*/ { /* seg segment to empty state, but do no reallocate it */ seg_check(s); s->seg_pos = 0; s->seg_maxpos = 0; } void segment_free(Segment s) /*;segment_free*/ { seg_check(s); efreet(s->seg_data, "segment-data"); efreet((char *) s, "segment"); } int segment_get_int(Segment s, int i) /*;segment_get_int*/ { /* get value of word from location i in segment seg. */ int *resp; seg_check(s); if (i >= s->seg_maxpos) { chaos("segment.c: get_int retrieving from undefined location\n"); return 0; } if (s->seg_kind == SEGMENT_KIND_DATA) { resp = (int *) s->seg_data + i; return *resp; } else { #ifdef ALIGN_WORD /* retrieve byte by byte to avoid alignment problems */ register int j; int v; register char *sp, *tp; resp = (int *) (s->seg_data + i); sp = (char *) resp; tp = (char *) &v; for (j = 0; j < sizeof(int); j++) *tp++ = *sp++; return v; #else resp = (int *) (s->seg_data + i); return *resp; #endif } } unsigned int segment_get_pos(Segment seg) /*;segment_get_pos*/ { seg_check(seg); return seg->seg_pos; } unsigned int segment_get_maxpos(Segment seg) /*;segment_get_maxpos*/ { seg_check(seg); return seg->seg_maxpos; } int segment_get_off(Segment s, int i) /*;segment_get_off*/ { return segment_get_int(s, i); } void segment_put_byte(Segment s, int v) /*;segment_put_byte*/ { unsigned newpos, pos; seg_check(s); if (s->seg_kind != SEGMENT_KIND_CODE) chaos("segment.c: segment_put_byte called on data segment"); pos = s->seg_pos; newpos = pos + 1; if (newpos >= s->seg_dim) { segment_realloc(s, newpos); } s->seg_data[pos] = (char) v; s->seg_pos = newpos; if (s->seg_maxpos < newpos) s->seg_maxpos = newpos; } void segment_put_const(Segment seg, Const con) /*;segment_put_const*/ { if (con->const_kind == CONST_INT) { /* can safely put integers - defer others for later */ segment_put_word(seg, INTV(con)); } else if(con->const_kind == CONST_REAL) { segment_put_real(seg, REALV(con)); } else if(con->const_kind == CONST_FIXED) { segment_put_long(seg, FIXEDV(con)); } else { #ifdef DEBUG zpcon(con); #endif chaos("segment.c - meaningless kind of literal"); } } void segment_put_int(Segment s, int v) /*;segment_put_int*/ { unsigned newpos, pos; int *d; seg_check(s); pos = s->seg_pos; if (s->seg_kind == SEGMENT_KIND_DATA) { newpos = pos + 1; if (newpos >= s->seg_dim) segment_realloc(s, newpos); d = (int *) s->seg_data; d[pos] = v; } else { /* if code segment */ newpos = pos + sizeof(int); if (newpos >= s->seg_dim) segment_realloc(s, newpos); #ifdef ALIGN_WORD /* if must worry about alignment, do byte by byte */ { int iv; iv = v; (void) segment_put_n(s, s->seg_pos, sizeof(int), (char *) &iv); } #else d = (int *) (s->seg_data + pos); *d = v; #endif } s->seg_pos = newpos; if (s->seg_maxpos < newpos) s->seg_maxpos = newpos; } void segment_put_long(Segment s, long v) /*;segment_put_long*/ { long lv = v; segment_put_n(s, s->seg_pos, sizeof(long), (char *) &lv); } static void segment_put_n(Segment s, int i, int n, char *p) /*;segment_put_n*/ { /* put n bytes from p at location i in segment seg, extending * segment if necessary */ unsigned newpos, pos; int *d; char *dc; seg_check(s); segment_set_pos(s, (unsigned) i, 0); pos = s->seg_pos; if (s->seg_size == 1) { /* if code segment */ newpos = pos + n; if (newpos >= s->seg_dim) segment_realloc(s, newpos); dc = s->seg_data + pos; while (n--) *dc++ = *p++; } else { /* assume word size */ newpos = pos + n/sizeof(int); if (newpos >= s->seg_dim) segment_realloc(s, newpos); d = (int *)( s->seg_data) + pos; dc = (char *) d; while (n--) *dc++ = (unsigned char) *p++; } s->seg_pos = newpos; if (s->seg_maxpos < newpos) s->seg_maxpos = newpos; } void segment_put_off(Segment s, int i, int v) /*;segment_put_off*/ { /* put value of v, interpreted as offset (16 bits) at location i * in segment seg. * We assume this is used to overwrite a previously defined location * and raise chaos if this is not the case. */ unsigned pos, oldpos; int *d; seg_check(s); if (i >= s->seg_maxpos) chaos("segment.c: segment_put_off of undefined location"); pos = i; if (s->seg_kind == SEGMENT_KIND_DATA) { d = (int *) s->seg_data; d[pos] = v; } else { #ifdef ALIGN_WORD { int iv; iv = v; oldpos = s->seg_pos; /* save pos since segment_put_n may alter it */ segment_put_n(s, i, sizeof(int), (char *)&iv); s->seg_pos = oldpos; } #else d = (int *) (s->seg_data + pos); *d = v; #endif } } void segment_put_real(Segment s, double db) /*;segment_put_real*/ { float r = db; segment_put_n(s, s->seg_pos, sizeof(float), (char *) &r); } void segment_put_ref(Segment seg, int segnum, int off) /*;segment_put_ref*/ { if (seg->seg_kind == SEGMENT_KIND_DATA) { segment_put_int(seg, segnum); segment_put_int(seg, off); } else { segment_put_byte(seg, segnum); segment_put_int(seg, off); } } void segment_put_word(Segment s, int v) /*;segment_put_word*/ { segment_put_int(s, v); } void segment_set_pos(Segment s, unsigned pos, unsigned offtyp) /*;segment_set_pos*/ { /* set position of segment to offset pos. offtyp is type of offset, * interpreted similarly to lseek(2); i.e., offtyp is 0 for offset * from start of segment, 1 for offset from current position, and 2 * for offset from end of segment. Only the cases 0 and 2 are supported now. */ seg_check(s); if (offtyp == 2) { /* to position at end ignore pos */ s->seg_pos = s->seg_maxpos; return; } if (offtyp != 0) chaos("segment_set_pos bad offset type"); s->seg_pos = pos; } static void segment_realloc(Segment s, unsigned newdim) /*;segment_realloc*/ { /* extend dimension field if necessary to it is at least as large * as newdim */ unsigned incr, dim; seg_check(s); dim = s->seg_dim; if (dim >= newdim) return; incr = newdim - dim; if (incr < s->seg_extend) incr = s->seg_extend; s->seg_dim += incr; s->seg_data = erealloct(s->seg_data, s->seg_dim * s->seg_size, "segment-realloc"); /* update ptr to data if one is being kept */ if (s->seg_ptr != (int **) 0) { *(s->seg_ptr) = (int *) s->seg_data; } } Segment template_new(int t_kind, int t_size, int words, int **ptr) /*;template_new*/ { Segment s; s = segment_new(SEGMENT_KIND_DATA, words); s->seg_ptr = ptr; /* save address of pointer to be updated */ /* return pointer to start of segment */ *(s->seg_ptr) = (int *) s->seg_data; segment_put_word(s, t_kind); segment_put_word(s, t_size); /* assume user will fill in rest direcly so point to end */ s->seg_pos = s->seg_maxpos = words; return s; } unsigned int PC() /*;PC*/ { /* corresponds to macro PC in SETL version */ seg_check(CODE_SEGMENT); return CODE_SEGMENT->seg_maxpos; } #ifdef DEBUG void zpseg(Segment seg) /*;zpseg*/ { printf("Segment %d x%x ", (int)seg, seg); if (seg->seg_kind == SEGMENT_KIND_CODE) printf(" code"); else printf(" data"); printf(" size %d pos %d max_pos %d dim %d ext %d\n", seg->seg_size, seg->seg_pos, seg->seg_maxpos, seg->seg_dim, seg->seg_extend); /* should print part of data here */ } #endif
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.