/* io.c 28 April 1999 */ /* copyright 1987,1988,1989 Phil Andrews, Pittsburgh Supercomputing Center */ /* all rights reserved */ /* handle the I/O in this module */ # include # include # include # include "defs.h" static int list_io; /* do some listing */ #define max_str 128 #define ctrl_g '\007' /* ring bell */ #define lf '\012' /* line feed, end of record */ #define ctrl_m '\015' /* leave graphics mode and do */ #define byte_size 8 /* 8 bits to the byte */ /* output characteristics */ static int out_size, rec_cr, fixed_size, bytes_gone, next_wanted, highest_rec; /* For optimization. */ static char digits[10] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}; #define max_pwrs 8 static int pwrs[max_pwrs] = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000}; /* input characteristics */ static int in_rec, poss_random; /* now the RMS I/O stuff */ #ifdef VMS /* these are for VMS calls */ #include rms #include ssdef /* systems services commands */ #include descrip /* for descriptors */ #include climsgdef /* CLI interface */ #include iodef /* for QIO's */ #include ttdef /* tty flags */ #include dcdef /* device flags */ #include stat /* UNIX fstat command */ /* this from the old trn.h file */ #define LNM$_STRING 2 #define LNM$M_CASE_BLIND 33554432 /* this is from the old jbc.h file */ #define SJC$_ADD_FILE 2 #define SJC$_CLOSE_JOB 9 #define SJC$_CREATE_JOB 10 #define SJC$_DELETE_FILE 24 #define SJC$_FILE_SPECIFICATION 42 #define SJC$_JOB_NAME 79 #define SJC$_JOB_STATUS_OUTPUT 88 #define SJC$_NOTIFY 108 #define SJC$_QUEUE 134 /* take care of C 2.3 change */ #ifndef RMS$_FILEPURGED #define RMS$_FILEPURGED 0x10679 #endif /* still VMS specific */ static int rms_status; extern int LIB$SIGNAL(); #define do_rms(rms_fun, rms_arg) { rms_status = rms_fun(rms_arg);\ if(rms_status != RMS$_NORMAL) {printf("\nerror in rms_fun");\ LIB$SIGNAL(rms_status);} } /* blocks for the metafile */ static struct FAB datfbl; /* to open the file */ static struct RAB datrbl; /* record operations */ static struct NAM datnbl; /* parse file name */ static struct XABFHC datxbl; /* file header info */ /* blocks for the output file */ static struct FAB ofbl; /* to open the file */ static int ofbl_open = 0; static struct RAB orbl; /* record operations */ static struct NAM onbl; /* parse file name */ static struct NAM nbl; /* name block */ /* blocks for the dvi file */ static struct FAB dvifbl; static struct RAB dvirbl; static struct XABFHC dvixbl; static struct NAM dvinbl; #else static FILE *inptr = NULL, *outptr, *dvifile; /* input and output pointers */ #endif static int block_size, record_size; /* unsigned char *realloc(); */ unsigned char *allocate_mem(); #define max_b_size 1024 static int out_b_size; /* output buffer (how much can use) */ static int b_ind = 0; /* index into array */ static char out_buffer[max_b_size]; /* buffer (max available) */ static int dat_open = 0; /* did we open a metafile */ extern char g_in_name[]; /* record buffer stuff */ static char *start_buf, *end_buf, *buf_ptr; static int buf_size; /* input buffer size */ static int recs_got; /* how many records read so far */ static int bytes_read; /* how many bytes read so far */ #define map_size 4 /* may have to remap the bytes */ static int need_map; #define poss_maps 4 /* for now */ static unsigned char poss_map[poss_maps][map_size] = { {0, 1, 2, 3}, {1, 0, 3, 2}, {3, 2, 1, 0}, {2, 3, 0, 1} }; static int ncar = 0; /* is this an ncar file ? */ static int skip_header = 0; /* do we want to skip some bytes ? */ /* NCAR header flags */ #define m_header 4 #define m_ncar_printer 8 #define m_old_meta 2 #define m_ext_cgm 3 #define m_new_frame 8 #define m_beg_meta 4 #define m_end_meta 2 #define m_cont_frame 0 /* now the NCAR header format */ struct header_type { /* the structure for the header */ unsigned char byte1; /* real bytes (2) used in record */ unsigned char byte2; /* real bytes (2) used in record */ unsigned char flags; /* various flags */ char dummy; /* low-order byte (1) not used */ }; /* function to get some more binary cgm bytes, returns zero if have problem */ /* assume already massaged */ int cgm_bytes(mem_ptr, no_bytes) char *mem_ptr; /* where to start putting the bytes */ int no_bytes; /* how many to put */ { int bytes_done = 0, bytes_got, header_bytes, data_bytes; char *my_ptr; if (no_bytes == 0) return(1); /* nothing to do */ if (no_bytes < 0) { fprintf(stderr, "illegal cgm_byte request %d\n", no_bytes); return(0); } /* now real requests */ my_ptr = mem_ptr; while (bytes_done < no_bytes) { if (buf_ptr >= end_buf) { /* need new record */ bytes_got = get_record(start_buf, buf_size); if (!bytes_got) return(0); header_bytes = massage_record(start_buf, bytes_got); data_bytes = process_header(start_buf, bytes_got); buf_ptr = start_buf + header_bytes; end_buf = buf_ptr + data_bytes; } else { *my_ptr++ = *buf_ptr++; ++bytes_done; } } return(1); } /* get the next clear text byte */ char clear_byte(out_ad) struct ad_struct *out_ad; /* address of command */ { int bytes_got; char cret; /* fill out the command address, may be about to get another record */ out_ad->r_ad = recs_got; out_ad->offset = buf_ptr - start_buf; if (buf_ptr >= end_buf) { /* need new record */ out_ad->offset = 0; ++out_ad->r_ad; } out_ad->b_ad = bytes_read - (end_buf - buf_ptr); if (buf_ptr >= end_buf) { /* need new record */ bytes_got = get_record(start_buf, buf_size); if (bytes_got < 0) { fprintf(stderr, "trouble getting the next clear record\n"); return(0); } buf_ptr = start_buf; end_buf = buf_ptr + bytes_got; /* send back a space for the end of record for VMS */ #ifdef VMS return(' '); #endif } cret = *buf_ptr++; return(cret); } /* read any implementation-specific record header */ process_header(header_ptr, total_bytes) char *header_ptr; int total_bytes; #define dbwrite(str) if (list_io) fprintf(stderr, str); { struct header_type *header_record; int itemp, ret1, ret2, tot_bytes; if (!ncar) return(total_bytes - skip_header); header_record = (struct header_type *) header_ptr; if (header_record->dummy != 0) fprintf(stderr, "dummy != 0, = %d\n", header_record->dummy); switch ( itemp = (header_record->flags >> 4) ) { case m_header : dbwrite("header\n"); break; case m_ncar_printer : dbwrite("NCAR printer\n"); break; case m_old_meta : dbwrite("old NCARmetafile\n"); break; case m_ext_cgm : dbwrite("NCAR CGEM\n"); break; default : fprintf(stderr, "data flag = %d ?", itemp); } switch ( itemp = (header_record->flags % 16) ) { case m_new_frame : dbwrite("new NCAR frame\n"); break; case m_beg_meta : dbwrite("begin NCAR metafile\n"); break; case m_end_meta : dbwrite("end NCAR metafile\n"); break; case m_cont_frame : dbwrite("cont. NCAR frame\n"); break; default : fprintf(stderr, "start flag = %d ?", itemp); } ret1 = header_record->byte1 << byte_size; ret2 = (header_record->byte2 & 255); tot_bytes = ret1 + ret2; if (tot_bytes % 2) ++tot_bytes; /* must be even */ return(tot_bytes); } /* need to set NCAR variable and byte map */ check_format(local_rec, size) unsigned char *local_rec; int size; { int i, j, k; unsigned int class, element; unsigned char new_set[map_size]; struct header_type *header_record; /* there are three issues: the necessary mapping to get the byte order correct, whether it is an NCAR file with its own record structure, or whether it ha a single header at the beginning that must be skipped */ if (size < map_size) { fprintf(stderr, "too few bytes (%d)!\n", size); return(0); } /* look for NCAR type files first */ for (i = 0; i < poss_maps; ++i) { for (j=0; j < map_size; ++j) new_set[j]=local_rec[poss_map[i][j]]; header_record = (struct header_type *) new_set; if (((header_record->flags >> 4) == m_ext_cgm) && (header_record->dummy == 0) && ((header_record->flags % 16) == m_beg_meta)) { ncar = 1; need_map = i; return(1); } } /* now look for a beginning B_Mf (vanilla format) */ for (i = 0; i < poss_maps; ++i) { for (j=0; j < map_size; ++j) new_set[j]=local_rec[poss_map[i][j]]; class = new_set[0] >> 4; element = ((new_set[0] << 3) & 127) + (new_set[1] >> 5); if ((class == 0) && (element == (int) B_Mf)) { /* no header */ ncar = 0; need_map = i; return(1); } } /* do we have a military header ? */ for (i = 0; i < poss_maps; ++i) { for (j=0; j < map_size; ++j) new_set[j]=local_rec[poss_map[i][j]]; /* for now define a military type header as being all printable */ for (k=0; (k=' ') && (new_set[k]<='z'); ++k); if (k==map_size) { skip_header = 7 * 80; /* bytes */ return(1); } } /* maybe a LANL header ? */ for (i = 0; i < poss_maps; ++i) { for (j=0; j < map_size; ++j) new_set[j]=local_rec[poss_map[i][j]]; if (new_set[0] == 1) { skip_header = 360; return(1); } } /* probably can't recover */ fprintf(stderr, "unknown header format !\n"); return(0); } /* massage record into correct format */ massage_record(local_rec, size) unsigned char *local_rec; int size; { int i, j, header_size; unsigned char *cptr; unsigned char new_set[map_size]; if (need_map) { /* need to rmap the bytes */ cptr = local_rec; for (i=0; i < ((size + map_size - 1) / map_size); ++i) { for (j=0; j < map_size; ++j) new_set[j] = cptr[poss_map[need_map][j]]; for (j=0; j < map_size; ++j) cptr[j] = new_set[j]; cptr += map_size; } } /* may have a variable header size here */ if (ncar) header_size = 4; else if (skip_header > 0) header_size = skip_header; else header_size = 0; return(header_size); } /* open up the input file */ open_input_file(file_name, o_name, talk, def_name, full_oname, in_info, c_text, random_file) char *file_name, *o_name, *def_name, *full_oname; int talk, c_text, *random_file; struct info_struct *in_info; { #define ncar_size 1440 unsigned char *allocate_mem(); int bytes_got, header_bytes, data_bytes, i, last_bytes_got; recs_got = 0; /* no records yet */ bytes_read = 0; /* nor bytes */ if (!(buf_size = open_metafile(file_name, def_name, o_name, full_oname, 1, talk, random_file))) return(0); if (list_io) (void) fprintf(stderr, "buffer size is %d bytes\n", buf_size); start_buf = (char *) allocate_mem(buf_size, 0); /* allocate buffer */ if (!start_buf) exit(0); /* get the first non-zero record */ while (!(bytes_got = get_record(start_buf, buf_size))); if (bytes_got < 0) { fprintf(stderr, "can't get the first record\n"); return(0); } /* what type of file is it ? */ ncar = skip_header = need_map = 0; if ((!c_text) && (!check_format(start_buf, bytes_got))) return(0); /* can't recognise it */ /* have recognized the file, but may have to deal with a header */ /* have to concern ourselves about NCAR format files */ if (ncar && (buf_size != ncar_size)) { #ifdef VMS fprintf(stderr, "bad format NCAR file, convert to ncar_size records\n"); return(0); #else if (buf_size < ncar_size) { start_buf = (char *) realloc(start_buf, ncar_size); if (!start_buf) exit(0); } buf_size = ncar_size; rewind(inptr); /* start again */ /* get the first non-zero record */ while (!(bytes_got = get_record(start_buf, buf_size))); if (bytes_got < 0) { fprintf(stderr, "can't get the first record\n"); return(0); } #endif } /* may be a one time header */ if (skip_header) { #ifdef VMS /* record-oriented */ last_bytes_got = bytes_got; while (skip_header > last_bytes_got) { skip_header -= last_bytes_got; if ((bytes_got = get_record(start_buf, buf_size)) < 0) { fprintf(stderr, "couldn't get header (%d)\n", skip_header); return(0); } last_bytes_got = bytes_got; } #else /* byte oriented */ rewind(inptr); while (skip_header >= buf_size) { if ((bytes_got = get_record(start_buf, buf_size)) < 0) { fprintf(stderr, "couldn't get header (%d)\n", skip_header); return(0); } skip_header -= bytes_got; } while (skip_header > 0) { if ((bytes_got = get_record(start_buf, skip_header)) < 0) { fprintf(stderr, "couldn't get header (%d)\n", skip_header); return(0); } skip_header -= bytes_got; } /* now get a fresh set */ bytes_got = get_record(start_buf, buf_size); #endif } /* carry on, possibly handling a header */ header_bytes = massage_record(start_buf, bytes_got); data_bytes = process_header(start_buf, bytes_got); /* initialise the pointers */ buf_ptr = start_buf + header_bytes; end_buf = buf_ptr + data_bytes; if (skip_header) skip_header = 0; /* one-time charge */ return(buf_size); } /* open the meta file */ open_metafile(file_name, def_name, o_name, full_oname, last_try, talk, random_file) char *file_name, *def_name, *o_name, *full_oname; int last_try, talk, *random_file; { #ifdef VMS static char try_name[NAM$C_MAXRSS + 1] = ""; static char actual_name[NAM$C_MAXRSS + 1] = ""; int mem_wanted; /* initialize RMS stuff */ datfbl = cc$rms_fab; datnbl = cc$rms_nam; datrbl = cc$rms_rab; datxbl = cc$rms_xabfhc; datfbl.fab$l_fna = file_name; /* what we're given */ datfbl.fab$b_fns = strlen(file_name); datfbl.fab$l_dna = def_name; /* the default */ datfbl.fab$b_dns = strlen(def_name); datfbl.fab$l_nam = &datnbl; /* name block */ datfbl.fab$b_fac = FAB$M_GET; /* open to read */ datnbl.nam$l_rsa = actual_name; /* what we opened */ datnbl.nam$b_rss = sizeof actual_name - 1; datnbl.nam$l_esa = try_name; /* what we tried to open */ datnbl.nam$b_ess = sizeof try_name - 1; datfbl.fab$l_xab = &datxbl; /* header info */ rms_status = sys$open(&datfbl); actual_name[datnbl.nam$b_rsl] = '\0'; try_name[datnbl.nam$b_esl] = '\0'; switch (rms_status) { case RMS$_NORMAL: if (talk) fprintf(stderr, "%s\n",actual_name); dat_open = 1; break; case RMS$_FNF: if ((last_try) && (talk)) fprintf(stderr, "couldn't find file %s\n", try_name); return(0); case RMS$_DNF: if ((last_try) && (talk)) fprintf(stderr, "couldn't find directory for %s\n", try_name); return(0); case RMS$_PRV: if ((last_try) && (talk)) fprintf(stderr, "insufficient privilege to open %s\n", try_name); return(0); default: LIB$SIGNAL(rms_status); return(0); } /* can we do random access input ? */ *random_file = poss_random = ( (datfbl.fab$b_org == FAB$C_SEQ) && (datfbl.fab$b_rfm == FAB$C_FIX) )||(datfbl.fab$b_rfm == FAB$C_REL); in_rec = 0; /* none got yet */ if (poss_random) { /* may do some random access I/O */ datrbl.rab$b_rac = RAB$C_KEY; datrbl.rab$b_ksz = 4; datrbl.rab$l_kbf = &in_rec; } /* put the actual name (eventually) into output string */ strcpy(full_oname, actual_name); /* send back the file name only for further use */ strncpy(o_name, datnbl.nam$l_name, (int) datnbl.nam$b_name); o_name[datnbl.nam$b_name] = '\0'; datrbl.rab$l_fab = &datfbl; /* connect file and record */ do_rms(sys$connect, &datrbl); mem_wanted = (datxbl.xab$w_lrl > datfbl.fab$w_mrs) ? datxbl.xab$w_lrl : datfbl.fab$w_mrs; if ((!mem_wanted) && /* no good info yet */ (datfbl.fab$b_rfm == FAB$C_STMLF)) { /* UNIX file */ mem_wanted = 1024 * 16; /* try something big */ } if (!mem_wanted) /* no good info */ mem_wanted = BUFSIZ; /* good as anything */ return(mem_wanted); #else char unix_name[256]; if (file_name[0] == '-') inptr = stdin; /* purposely redirected */ else if (*file_name) { if (NULL == (inptr = fopen(file_name, "r"))) { (void) fprintf(stderr, "couldn't fopen to read %s\n", file_name); perror("open_metafile"); return(0); } } else { fprintf(stderr, "no file name, will use stdin\n"); inptr = stdin; } #ifdef VAXC (void) fgetname(inptr, unix_name); strcpy(full_oname, unix_name); fprintf(stderr, "%s\n", unix_name); *random_file = 0; /* no random access */ #else strcpy(full_oname, file_name); *random_file = 1; /* UNIX can do it (I hope) */ #endif strncpy(o_name, file_name, max_str); return(BUFSIZ); #endif } /* open the output device here */ #ifdef VMS open_file(file_name, def_name, o_name, fbl, for_output) char *file_name, *def_name, *o_name; struct FAB *fbl; /* file block */ int for_output; { char try_name[NAM$C_MAXRSS + 1]; char actual_name[NAM$C_MAXRSS + 1]; nbl = cc$rms_nam; /* global name block */ fbl->fab$l_fna = file_name; /* what we're given */ fbl->fab$b_fns = strlen(file_name); fbl->fab$l_dna = def_name; /* the default */ fbl->fab$b_dns = strlen(def_name); fbl->fab$l_nam = &nbl; /* name block */ nbl.nam$l_rsa = actual_name; /* what we opened */ nbl.nam$b_rss = sizeof actual_name - 1; nbl.nam$l_esa = try_name; /* what we tried to open */ nbl.nam$b_ess = sizeof try_name - 1; fbl->fab$b_rat = 0; /* carriage return */ fbl->fab$b_fac = (for_output) ? FAB$M_PUT : FAB$M_GET ; fbl->fab$b_shr = FAB$M_SHRGET; /* now open it */ rms_status = sys$open(fbl); actual_name[nbl.nam$b_rsl] = '\0'; try_name[nbl.nam$b_esl] = '\0'; switch (rms_status) { case RMS$_CREATED: if (list_io) fprintf(stderr, "\ncreated file %s\n", actual_name); break; case RMS$_NORMAL: if (list_io) fprintf(stderr, "\nopened file %s for %s\n",actual_name, (for_output) ? "output" : "input"); break; case RMS$_FNF: fprintf(stderr, "\ncouldn't find file %s\n", try_name); return(0); break; case RMS$_DNF: fprintf(stderr, "\ncouldn't find directory for %s\n", try_name); return(0); break; case RMS$_PRV: fprintf(stderr,"\ninsufficent privilege for %s\n", try_name); return(0); default: fprintf(stderr, "\ncouldn't open %s\n", try_name); LIB$SIGNAL(rms_status); return(0); } /* send back the whole name for further use */ sprintf(o_name, "%s", actual_name); return(1); } #endif /* function to read in a complete data record */ get_record(local_rec, size) unsigned char *local_rec; int size; { int ret, bytes_in; ++recs_got; /* at least tried */ #ifdef VMS datrbl.rab$w_usz = size; datrbl.rab$l_ubf = local_rec; ++in_rec; ret = SYS$GET(&datrbl); bytes_in = datrbl.rab$w_rsz; if (datfbl.fab$b_rfm == FAB$C_STMLF) { /* UNIX file */ if (bytes_in >= size) return(-1); local_rec[bytes_in] = lf; ++bytes_in; } bytes_read += bytes_in; if (ret != RMS$_NORMAL) { LIB$SIGNAL(ret); return(-1); } else return(bytes_in); #else /* unix stuff */ ret = fread(local_rec, 1, size, inptr); bytes_read += ret; return(ret); #endif } /* finish up */ close_up(inc) int inc; { if (list_io) fprintf(stderr, "\nEnd Metafile\n"); #ifdef VMS if (dat_open) do_rms(SYS$CLOSE, &datfbl); /* close the metafile */ #else if ((inptr != NULL) && (inptr != stdin)) fclose(inptr); #endif if (inc) return(1); close_out_file(); return(1); } /* take care of the output files here */ open_output_file(file_name, def_name, do_list, in_info) char *file_name, *def_name; int do_list; struct info_struct *in_info; { int i, name_length; char list_name[max_str], unix_name[256], *my_ptr; /* set some locals */ next_wanted = 0; /* sequential default */ highest_rec = 1; /* start output at record one */ bytes_gone = 0; out_b_size = (in_info->rec_size < max_b_size) ? in_info->rec_size : max_b_size; for (i=0; icapability & need_fix); rec_cr = !(in_info->capability & no_cr); /* first look to see if we want to redirect output */ list_io = do_list; if (list_io) { /* first go past any directory specs */ name_length = strlen(file_name); my_ptr = file_name + name_length; while ((my_ptr >= file_name) && (*my_ptr != '/')) --my_ptr; ++my_ptr; for (i=0; (*my_ptr) && (*my_ptr != '.'); ++i) list_name[i] = *(my_ptr++); sprintf(list_name + i, "%s", ".lis"); if (NULL == freopen(list_name, "w", stderr)) fprintf(stderr, "couldn't reopen %s\n", list_name); } #ifdef VMS if (!strlen(def_name)) return(1); /* no output file */ if ((0 == strcmp(def_name, "SYS$OUTPUT:")) && (!list_io)) {/* to tty */ sprintf(list_name, "%s%s", file_name, ".lis"); if (!freopen(list_name, "w", stderr)) printf("couldn't reopen stderr !\n"); } return(open_rms_file(file_name, def_name, out_b_size, rec_cr, fixed_size)); #else if (def_name[0] == '\0') { outptr = stdout; return(1); } else if (NULL == (outptr = fopen(def_name, "w+"))) { (void) fprintf(stderr, "couldn't fopen to write %s\n", def_name); perror("open_output_file"); return(0); } else { #ifdef VAXC (void) fgetname(outptr, unix_name); fprintf(stderr, "%s\n", unix_name); make_lnm("GPT$OUTPUT", "LNM$JOB", unix_name); #endif return(1); } #endif } /* take care of getting the next command and all of its data into memory */ /* note that we must always round up the no. of bytes to an even no. */ #define round_up(a) (a = (a % 2) ? a + 1 : a) get_cmd(mem_ptr, mem_size, out_ad) int *mem_size; /* how much memory got */ char *(*mem_ptr); /* ptr to a ptr */ struct ad_struct *out_ad; /* address of command */ { char *my_ptr, *new_ptr, *start_ptr, first_byte, second_byte; int p_len, i, cgm_bytes(), int_len, done = 0, new_size; unsigned char sec_word[2]; start_ptr = my_ptr = *mem_ptr; /* beginning of allocated memory */ /* fill out the command address, may be about to get another record */ out_ad->r_ad = recs_got; out_ad->offset = buf_ptr - start_buf; if (buf_ptr >= end_buf) { /* need new record */ out_ad->offset = 0; ++out_ad->r_ad; } out_ad->b_ad = bytes_read - (end_buf - buf_ptr); if (!cgm_bytes(my_ptr, 2)) return(-1); first_byte = *my_ptr; second_byte = *(my_ptr + 1); p_len = second_byte & 31; my_ptr += 2; /* step forward */ if (p_len < 31) { /* short form command */ round_up(p_len); if (!cgm_bytes(my_ptr, p_len)) return(-1); else return(p_len); } /* now handle long format */ p_len = 0; while (!done) { if (!cgm_bytes(sec_word, 2)) return(-1); int_len = ((sec_word[0] & 127) << byte_size) | sec_word[1]; round_up(int_len); if ( (new_size = (p_len + 2 + int_len)) > *mem_size ) { *mem_ptr = (char *) realloc(*mem_ptr, new_size); if (!*mem_ptr) { fprintf(stderr, "couldn't allocate enough memory, aborting\n"); exit(0); } else fprintf(stderr, "grabbing more memory, %d -> %d\n", *mem_size, new_size); my_ptr = *mem_ptr + 2 + p_len; *mem_size = new_size; } if (!cgm_bytes(my_ptr, int_len)) return(-1); p_len += int_len; my_ptr += int_len; done = !(sec_word[0] & (1 << 7)); } return(p_len); } #undef round_up /* RMS output stuff */ /* get it ready */ void init_buffer() { int i; for (i=0; i< out_b_size; ++i) out_buffer[i] = 0; b_ind = 0; } /* close it out */ close_out_file() { if (b_ind) fb(); #ifdef VMS if (ofbl_open) do_rms(SYS$CLOSE, &ofbl); #else #ifdef VAXC fputc(lf, outptr); ++bytes_gone; #endif if ((outptr) && (outptr != stdout)) fclose(outptr); #endif return(1); } /* open the output file here */ #ifdef VMS open_rms_file(file_name, def_name, rec_size, rec_cr, fix) int rec_size, rec_cr, fix; char *file_name, *def_name; { extern make_lnm(); /* in utils.c */ char try_name[NAM$C_MAXRSS + 1]; char actual_name[NAM$C_MAXRSS + 1]; ofbl = cc$rms_fab; /* initialize RMS stuff */ onbl = cc$rms_nam; orbl = cc$rms_rab; ofbl.fab$b_org = FAB$C_SEQ; /* sequential file */ ofbl.fab$b_rfm = (fix) ? FAB$C_FIX : FAB$C_VAR; /* record format */ ofbl.fab$l_fop = FAB$M_CBT; /* contiguous best try */ ofbl.fab$b_rat = (rec_cr) ? FAB$M_CR : 0; /* cr info */ ofbl.fab$w_mrs = rec_size; /* max record size */ orbl.rab$b_rac = (fix) ? RAB$C_KEY : RAB$C_SEQ; orbl.rab$b_ksz = 4; orbl.rab$l_rop = RAB$M_UIF; ofbl.fab$l_fna = file_name; /* what we're given */ ofbl.fab$b_fns = strlen(file_name); ofbl.fab$l_dna = def_name; /* the default */ ofbl.fab$b_dns = strlen(def_name); ofbl.fab$l_nam = &onbl; /* name block */ ofbl.fab$b_fac = FAB$M_GET | FAB$M_DEL | FAB$M_UPD | FAB$M_PUT; onbl.nam$l_rsa = actual_name; /* what we opened */ onbl.nam$b_rss = sizeof actual_name - 1; onbl.nam$l_esa = try_name; /* what we tried to open */ onbl.nam$b_ess = sizeof try_name - 1; rms_status = sys$create(&ofbl); actual_name[onbl.nam$b_rsl] = '\0'; try_name[onbl.nam$b_esl] = '\0'; /* actually open it */ switch (rms_status) { case RMS$_FILEPURGED: case RMS$_NORMAL: fprintf(stderr, "%s\n",actual_name); make_lnm("GPT$OUTPUT", "LNM$JOB", actual_name); ofbl_open = 1; break; case RMS$_FNF: fprintf(stderr, "couldn't find file %s\n", try_name); return(0); case RMS$_DNF: fprintf(stderr, "couldn't find directory for %s\n", try_name); return(0); case RMS$_PRV: fprintf(stderr, "insufficient privilege to open %s\n", try_name); return(0); default: LIB$SIGNAL(rms_status); return(0); } orbl.rab$l_fab = &ofbl; /* connect file and record */ do_rms(sys$connect, &orbl); init_buffer(); return(1); } #endif /* put out one char */ outc(inc) char inc; { if (b_ind >= out_b_size) fb(); out_buffer[b_ind++] = inc; return(1); } /* put out one char, but break if it's a line feed */ boutc(inc) char inc; { if (inc == '\012') { fb(); return(1); } if (b_ind >= out_b_size) fb(); out_buffer[b_ind++] = inc; return(1); } /* function asking where the output end is */ cgmb_inq(out_ad) struct ad_struct *out_ad; { out_ad->r_ad = highest_rec; out_ad->offset = b_ind; out_ad->b_ad = bytes_gone + b_ind; return(1); } /* function to position in output file */ cgmb_goto(in_ad) struct ad_struct *in_ad; { #ifdef VMS next_wanted = in_ad->r_ad; #else /* UNIX */ if (fseek(outptr, in_ad->b_ad, 0)) { fprintf(stderr, "illegal fseek to %d\n", in_ad->b_ad); perror("cgmb_goto"); return(0); } bytes_gone = in_ad->b_ad; /* how many out before us */ #endif return(1); } /* function to position in input file */ cgm_goto(in_ad) struct ad_struct *in_ad; { #ifdef VMS int header_bytes, data_bytes, bytes_got, i; if (!poss_random) { /* no random access */ rms_status = sys$rewind(&datrbl); if (rms_status != RMS$_NORMAL) { LIB$SIGNAL(rms_status); return(0); } for (i=1; ir_ad; ++i) (void) get_record(start_buf, buf_size); } in_rec = in_ad->r_ad - 1; recs_got = in_rec; bytes_read = recs_got * buf_size; bytes_got = get_record(start_buf, buf_size); header_bytes = massage_record(start_buf, bytes_got); data_bytes = process_header(start_buf, bytes_got); if (in_ad->offset > data_bytes) { fprintf(stderr, "illegal offset %d\n", in_ad->offset); return(0); } /* try quick fix for ncar files */ buf_ptr = (ncar) ? start_buf + header_bytes : start_buf + header_bytes + in_ad->offset; end_buf = start_buf + header_bytes + data_bytes; return(bytes_got); #else /* UNIX */ /* try quick fix for ncar files */ int byte_ad; byte_ad = (ncar) ? (in_ad->b_ad / ncar_size) * ncar_size : in_ad->b_ad; if (fseek(inptr, byte_ad, 0)) { fprintf(stderr, "illegal fseek to %d\n", byte_ad); perror("cgm_goto"); return(0); } bytes_read = byte_ad; /* where we've got to */ buf_ptr = end_buf; /* need more bytes */ return(1); #endif } /* function to fill out the address pointers in a new address given an old address and a byte offset from it */ /* a little tricky because we want to handle record/offset only cases also */ fill_ad(new_ad, last_ad, byte_offset) struct ad_struct *new_ad, *last_ad; long int byte_offset; { int new_rec, new_offset, rec_shift, bit_shift; long new_byte; if ((new_byte = byte_offset + last_ad->b_ad) < 0) { (void) fprintf(stderr, "negative byte address %d = %d + %d\n", new_byte, byte_offset, last_ad->b_ad); return(0); } else new_ad->b_ad = new_byte; /* remember truncation towards zero ! */ bit_shift = last_ad->offset + byte_offset; if (bit_shift >= 0) rec_shift = bit_shift / buf_size; else rec_shift = (bit_shift % buf_size) ? bit_shift / buf_size - 1 : bit_shift / buf_size; new_rec = last_ad->r_ad + rec_shift; #ifdef VMS if (new_rec < 1) { (void) fprintf(stderr, "illegal record address %d ", new_rec); return(0); } else new_ad->r_ad = new_rec; new_offset = last_ad->offset + byte_offset; #else /* just for consistency */ new_ad->r_ad = (new_byte + buf_size - 1) / buf_size; new_offset = new_byte % buf_size; #endif /* may be greater than buf_size */ if (new_offset >= buf_size) new_offset %= buf_size; /* may be negative */ while (new_offset < 0) new_offset += buf_size; new_ad->offset = new_offset; return(1); } /* funtion to put out a two byte arg for the aps */ out_short(inval) int inval; { char *temp; if ((b_ind + 1) >= out_b_size) fb(); temp = (char *)&inval; outc(*(temp + 1)); outc(*temp); return(1); } /* put out a positive fixed width integer, optimised, so a little risky */ outgint(inval, size) int inval, size; { static char gint_buffer[max_pwrs + 2]; register char *gint_ptr; register int i, j; if (inval < 0) { gint_buffer[0] = '-'; gint_ptr = gint_buffer + 1; inval = -inval; } else gint_ptr = gint_buffer; for (i=size-1; i>0; --i) { j = inval / pwrs[i]; *gint_ptr++ = digits[j]; if (j) inval -= j * pwrs[i]; } *gint_ptr++ = digits[inval]; *gint_ptr = '\0'; return(out_string(gint_buffer)); } /* put out a decimal, optimise */ doint(i) int i; { static char buffer[max_pwrs + 2]; register char *cptr; register int is_neg, j; cptr = buffer + max_pwrs + 1; *cptr = '\0'; if (i < 0) { is_neg = 1; i = -i; } else is_neg = 0; if (i == 0) { *--cptr = digits[0]; return(out_string(cptr)); /* all done */ } while (i) { j = i % 10; *--cptr = digits[j]; i /= 10; } if (is_neg) *--cptr = '-'; return(out_string(cptr)); } /* put out a formatted integer for CGMC */ intout(i) int i; { static char buffer[max_pwrs + 2]; register char *cptr; register int is_neg, j; int b_len; cptr = buffer + max_pwrs + 1; *cptr = '\0'; if (i < 0) { is_neg = 1; /* Special case: most negative number (not trivially negated) */ /* (workaround assumes two's complement) */ if (!(i << 1)) { *--cptr = digits[8]; i /= 10; } i = -i; } else is_neg = 0; if (i == 0) { *--cptr = digits[0]; } else while (i) { j = i % 10; *--cptr = digits[j]; i /= 10; } if (is_neg) *--cptr = '-'; b_len = buffer + max_pwrs + 1 - cptr; if ((b_ind > 0) && (b_len <= (out_b_size - b_ind))) outc(' '); return(out_string(cptr)); } /* put out a formatted integer in decimal, assume we want a space/nl after */ outint(i) int i; { int ret; ret = doint(i); if ((b_ind) && (b_ind < out_b_size)) return(outc(' ')); else return(ret); } /* process one string */ out_string(in_string) char *in_string; { int to_go, i; to_go = strlen(in_string); if (to_go <= (out_b_size - b_ind)) { for (i=0; i (out_b_size - b_ind) ) { for (b_ind=0; b_ind < out_b_size; ++b_ind) out_buffer[b_ind] = *in_string++; to_go -= out_b_size; fb(); } for (i=0; i 0) { if (next_wanted < highest_rec) { /* overwriting */ rec_wanted = next_wanted; ++next_wanted; } else if (next_wanted > highest_rec) { fprintf(stderr, "trying to jump past end of file, %d > %d\n", next_wanted, highest_rec); next_wanted = highest_rec; rec_wanted = highest_rec++; bytes_gone += bytes_to_go; } else if (next_wanted == highest_rec) { next_wanted = 0; /* back to sequential */ rec_wanted = highest_rec++; bytes_gone += bytes_to_go; } } else { rec_wanted = highest_rec++; bytes_gone += bytes_to_go; } orbl.rab$l_rbf = out_buffer; /* record address */ orbl.rab$w_rsz = bytes_to_go; orbl.rab$l_kbf = &rec_wanted; do_rms(SYS$PUT, &orbl); status = (rms_status == RMS$_NORMAL); #else status = fwrite(out_buffer, 1, bytes_to_go, outptr); bytes_gone += bytes_to_go; if (rec_cr) { fputc(lf, outptr); ++bytes_gone; } #endif b_ind = 0; for (i=0; i < out_b_size; ++i) out_buffer[i] = 0; return(status); } /* put out 16 bits in correct order for the imagen */ put_short(inval) int inval; #define first_eight 255 { char *temp; temp = (char *)&inval; outc(*(temp + 1)); outc(*temp); return(0); } /* open up a dvi file for GTEX */ dvi_open(file_name, def_name, o_name, allocated, used, full_name, quiet, byte_no, rec_size) char *file_name, *def_name, *o_name, *full_name; int *allocated, *used, quiet, *byte_no, *rec_size; { int i, j, tell_byte, last_offset; #ifdef VMS char try_name[NAM$C_MAXRSS + 1]; static char actual_name[NAM$C_MAXRSS + 1] = ""; /* initialize RMS stuff */ dvifbl = cc$rms_fab; dvinbl = cc$rms_nam; dvirbl = cc$rms_rab; dvixbl = cc$rms_xabfhc; dvifbl.fab$l_fna = file_name; dvifbl.fab$b_fns = strlen(file_name); dvifbl.fab$l_dna = def_name; dvifbl.fab$b_dns = strlen(def_name); dvifbl.fab$l_nam = &dvinbl; /* name block */ dvifbl.fab$b_shr = FAB$M_SHRGET; /* others can read it */ dvifbl.fab$l_xab = &dvixbl; /* header info */ dvinbl.nam$l_rsa = actual_name; dvinbl.nam$b_rss = sizeof actual_name - 1; dvinbl.nam$l_esa = try_name; j = dvinbl.nam$b_ess = i = sizeof try_name - 1; rms_status = sys$open(&dvifbl); actual_name[dvinbl.nam$b_rsl] = '\0'; try_name[dvinbl.nam$b_esl] = '\0'; switch (rms_status) { case RMS$_NORMAL: if (!quiet) fprintf(stderr, "%s",actual_name); break; case RMS$_FNF: fprintf(stderr, "couldn't find file %s", try_name); return(0); case RMS$_DNF: fprintf(stderr, "couldn't find directory for %s", try_name); return(0); case RMS$_PRV: fprintf(stderr, "insufficient privilege to open %s", try_name); return(0); default: LIB$SIGNAL(rms_status); return(0); } fprintf(stderr, "\n"); block_size = dvifbl.fab$w_bls; *rec_size = record_size = dvifbl.fab$w_mrs; if ( (block_size != record_size) || (record_size != 512) ){ fprintf(stderr, "\nrecord = %d, block = %d, != 512, trouble !", record_size, block_size); block_size = 512; } *allocated = dvifbl.fab$l_alq; last_offset = dvixbl.xab$w_ffb; if (last_offset == 0) { /* want previous record */ *used = dvixbl.xab$l_ebk - 1; last_offset = record_size - 1; } else { *used = dvixbl.xab$l_ebk; last_offset -= 1;; } *byte_no = (*used - 1) * record_size + last_offset; /* send back the file name only for further use */ strncpy(o_name, dvinbl.nam$l_name, (int) dvinbl.nam$b_name); o_name[dvinbl.nam$b_name] = '\0'; /* also send back the full path name */ strcpy(full_name, actual_name); /* set up the RAB fields */ dvirbl.rab$b_rac = RAB$C_KEY; /* random access */ dvirbl.rab$b_ksz = 4; dvirbl.rab$l_fab = &dvifbl; /* connect file and record */ do_rms(sys$connect, &dvirbl); /* UNIX stuff, do I/O in units of BUFSIZ */ #else *rec_size = block_size = record_size = BUFSIZ; if (NULL == (dvifile = fopen(file_name, "r"))) { (void) fprintf(stderr, "couldn't fopen %s\n", file_name); perror("dvi_open"); return(0); } strcpy(o_name, file_name); *def_name = '\0'; #ifdef VAXC (void) fgetname(dvifile, full_name); #else strcpy(full_name, file_name); #endif /* lets try to get to the end */ if (fseek(dvifile, 0, 2)) { fprintf(stderr, "illegal fseek\n"); perror("dvi_open"); } tell_byte = ftell(dvifile); *used = (tell_byte + block_size - 1) / block_size; *allocated = *used; *byte_no = tell_byte; #endif return(1); } /* go to a specific spot in the dvi file */ unsigned char *go_to(lead_byte, bytes_needed) int lead_byte, bytes_needed; { int first_record, last_record, mem_size, i, rel_record; static char *dvi_start = NULL; first_record = ((lead_byte + record_size) / record_size); last_record = ((lead_byte + bytes_needed - 1 + record_size) / record_size); mem_size = (last_record - first_record + 1) * record_size; if (first_record > last_record) { fprintf(stderr, "\ntrouble, first record = %d(%d), last = %d(%d)", first_record, lead_byte, last_record, lead_byte + bytes_needed - 1); mem_size = record_size; /* try to recover */ } dvi_start = dvi_start ? (char *) realloc(dvi_start, mem_size) : (char *) allocate_mem(mem_size, 0); if (dvi_start == 0) fprintf(stderr, "\ntrouble allocating memory,mem_size = %d", mem_size); #ifdef VMS for (i=0; i <= last_record - first_record; ++i) { dvirbl.rab$l_ubf = dvi_start + i * record_size; dvirbl.rab$w_usz = mem_size - i * record_size; rel_record = first_record + i; /* the rel. rec. no. */ dvirbl.rab$l_kbf = &rel_record; rms_status = SYS$GET(&dvirbl); if (rms_status != RMS$_NORMAL) { fprintf(stderr, "\ntrouble getting record %d, (%d,%d), lead_byte = %d, bytes_needed = %d", *dvirbl.rab$l_kbf, first_record, last_record, lead_byte, bytes_needed); LIB$SIGNAL(rms_status); } } #else if (fseek(dvifile, (first_record - 1) * record_size, 0)) { fprintf(stderr, "illegal fseek\n"); perror("go_to"); } fread(dvi_start, 1, (last_record - first_record + 1) * record_size, dvifile); #endif return((unsigned char *)dvi_start + (lead_byte % record_size)); } /* close the dvi file */ close_dvi() { #ifdef VMS do_rms(SYS$CLOSE, &dvifbl); #else fclose(dvifile); #endif return(1); } /* function to handle logging line */ log_line(instr, in_count, in_ptr, flush_out, first_call, line_flag) char *instr, **in_ptr; int in_count, flush_out, first_call, line_flag; { #define MAX_LINES 10 #define MAX_SIZE 128 static int line_no[MAX_LINES]; static char lines[MAX_LINES][MAX_SIZE + 1]; #ifdef VAXC #define USAGE_NAME "GPLOT$USAGE" #define TAB_NAME "LNM$FILE_DEV" #endif /* for now */ #ifdef USAGE_NAME /* is there anything to do ? */ int i, j, k; static int lines_used = 0; FILE *usage_ptr; #ifdef VAXC /* take care of VMS */ static char trans_result[128]; static int have_logical = 0; if (have_logical < 0) return(2); if (!have_logical && !(translate("GPLOT$USAGE", TAB_NAME, trans_result) &1)) { have_logical = -1; return(2); } else have_logical = 1; /* first store the command line */ #endif if (first_call) { line_no[lines_used] = 1; for (i=0; (i