/*- ****************************************************************************** ****************************************************************************** ** ** ARCHIVE HEADER INFORMATION ** ** @C-file{ ** FILENAME = "vvdecode.c", ** VERSION = "1.00", ** DATE = "", ** TIME = "", ** ** AUTHOR = "Niel Kempson", ** ADDRESS = "25 Whitethorn Drive, Cheltenham, GL52 5LL, England", ** TELEPHONE = "+44-242 579105", ** EMAIL = "kempson@tex.ac.uk (Internet)", ** ** SUPPORTED = "yes", ** ARCHIVED = "tex.ac.uk, ftp.tex.ac.uk", ** KEYWORDS = "VVcode", ** ** CODETABLE = "ISO/ASCII", ** CHECKSUM = "51492 1481 5732 57976", ** ** DOCSTRING = { This file is part of VVcode. ** } ** } ** ** ** MODULE CONTENTS ** ** ** COPYRIGHT ** ** Copyright (c) 1991-1993 by Niel Kempson ** ** 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 1, or ** (at your option) any later version. ** ** 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, write to the Free Software ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ** ** In other words, you are welcome to use, share and improve this ** program. You are forbidden to forbid anyone else to use, share ** and improve what you give them. Help stamp out software-hoarding! ** ** CHANGE LOG ** ****************************************************************************** ****************************************************************************** */ static char rcsid[] = "$Id$"; #define VVDECODE 1 #define VVCODE_MAIN 1 /*- **---------------------------------------------------------------------------- ** Standard include files **---------------------------------------------------------------------------- */ #include /*- **---------------------------------------------------------------------------- ** Include the machine specific definitions **---------------------------------------------------------------------------- */ #include "checkos.h" #include "machine.h" #include "local.h" #include "globals.h" #include "specific.h" #include "vvutils.h" #include "vveparse.h" /*- **---------------------------------------------------------------------------- ** Forward declarations of functions in this file **---------------------------------------------------------------------------- */ int main ARGS ((CONST int argc, CONST char *argv[])); Boolean choose_xlt_table ARGS ((CONST Qualifier_Struct *xlt_qualifier, CONST Qualifier_Struct *idx_qualifier, CONST char *from_charset, CONST char *to_charset, File_Info *xlt_file)); void decode ARGS ((void)); Int16 decode_bytes ARGS ((CONST Int16 bytes_left, CONST char *ip_buf_ptr, char *op_buf_ptr)); void find_next_part ARGS ((CONST Int16 part_needed, File_Info *ip_file_ptr)); void initialize ARGS ((void)); void open_ip_file ARGS ((CONST Qualifier_Struct *ip_qualifier, File_Info *ip_file)); void open_next_part ARGS ((CONST Int16 part_needed, File_Info *ip_file)); void open_op_file ARGS ((CONST Qualifier_Struct *op_qualifier, CONST Int16 overwrite_flag, CONST char *vve_hdr_spec, File_Info *op_file)); char *parse_enc_tbl ARGS ((CONST char *line_ptr, Header_Struct *hdr_struct, File_Info *ip_file)); Boolean prs_idx_file ARGS ((CONST char *from_charset, CONST char *to_charset, File_Info *idx_file, File_Info *xlt_file)); void rdfi_headers ARGS ((CONST Int16 decoding_type, File_Info *ip_file, Header_Struct *vve_hdr_array)); void rdfi_trailers ARGS ((CONST Int16 decoding_type, File_Info *ip_file, File_Info *vve_file, Header_Struct *vve_hdr_array)); void set_decoding_type ARGS ((CONST Qualifier_Struct *uu_qualifier, CONST Qualifier_Struct *xx_qualifier, Int16 *decoding_type, char **vve_line_prefix, char **vve_eol_marker)); void set_enc_tbl ARGS ((CONST Qualifier_Struct *enc_qualifier, CONST Int16 enc_tbl_len, char *encode_table)); void set_format ARGS ((CONST Qualifier_Struct *fmt_qualifier, CONST File_Info *vve_file, CONST char *vve_os_str, CONST char *fmt_str_array[], File_Info *op_file)); Boolean set_idx_file ARGS ((CONST Qualifier_Struct *idx_qualifier, File_Info *idx_file)); void set_mode ARGS ((CONST Qualifier_Struct *mode_qualifier, CONST File_Info *vve_file, CONST char *mode_str_array[], File_Info *op_file)); void set_pad_char ARGS ((CONST Qualifier_Struct *pad_qualifier, CONST File_Info *op_file, char *pad_char)); void set_record_len ARGS ((CONST Qualifier_Struct *rec_qualifier, CONST File_Info *vve_file, File_Info *op_file)); void set_timestamp ARGS ((CONST Qualifier_Struct *time_qualifier, CONST File_Info *vve_file, File_Info *op_file)); void terminate ARGS ((void)); void usage_error ARGS ((CONST char *reason)); /*- **============================================================================ ** ** FUNCTION ** ** choose_xlt_file ** ** DESCRIPTION ** ** [tbs] ** ** INPUT PARAMETERS ** ** xlt_file ** [tbs] ** ** OUTPUT PARAMETERS ** ** [tbs] ** ** RETURN VALUE ** ** TRUE - a candidate translation file was found ** FALSE - a candidate translation file could not be ** identified ** **============================================================================ */ #if (ANSI_SYNTAX) Boolean choose_xlt_table (CONST Qualifier_Struct *xlt_qualifier, CONST Qualifier_Struct *idx_qualifier, CONST char *from_charset, CONST char *to_charset, File_Info *xlt_file) #else /* NOT (ANSI_SYNTAX) */ Boolean choose_xlt_table (xlt_qualifier, idx_qualifier, xlt_file, from_charset, to_charset) CONST Qualifier_Struct *xlt_qualifier; CONST Qualifier_Struct *idx_qualifier; CONST char *from_charset; CONST char *to_charset; File_Info *xlt_file; #endif /* (ANSI_SYNTAX) */ { File_Info idx_file; Boolean status; /*- **------------------------------------------------------------------------ ** If the /TRANSLATION_FILE qualifier was specified, we use its value as ** the file specification for the translation table file. **------------------------------------------------------------------------ */ if (xlt_qualifier->present == TRUE) { strcpy (xlt_file->file_spec, xlt_qualifier->value); /*- **-------------------------------------------------------------------- ** If an extension has not been provided, use the default extension ** for the translation table file. **-------------------------------------------------------------------- */ #if (STICKY_DEFAULTS) apply_defaults (NULL, DEF_XLT_EXT, xlt_file->file_spec); #endif /* (STICKY_DEFAULTS) */ return (TRUE); } /*- **------------------------------------------------------------------------ ** The /TRANSLATION_FILE qualifier was not specified, so we look for an ** index file that might specify which translation file to use. The ** function set_idx_file() will determine which index file to use or ** return FALSE if it couldn't. **------------------------------------------------------------------------ */ status = set_idx_file (idx_qualifier, &idx_file); if (status != TRUE) { LOGMSG ("\nTranslation index file: none"); return (FALSE); } LOGMSG_1 ("\nTranslation index file: %s", idx_file.file_spec); /*- **------------------------------------------------------------------------ ** Now parse the index file to see if it contains an entry for the ** desired character set translation. **------------------------------------------------------------------------ */ status = prs_idx_file (from_charset, to_charset, &idx_file, xlt_file); return (status); } /* choose_xlt_table */ /*- **============================================================================ ** ** FUNCTION ** ** DEC_BYTE ** ** DESCRIPTION ** ** [tbs] ** ** INPUT PARAMETERS ** ** [tbs] ** ** OUTPUT PARAMETERS ** ** [tbs] ** ** RETURN VALUE ** ** [tbs] ** **============================================================================ */ #define DEC_BYTE(_from,_to) \ if (G_decode_table[(int) (_from)] == INV_TABLE_ENTRY)\ {\ FATALMSG_4 ("invalid character %d (0x%02X) on line %ld of file `%s'",\ (int) (_from), (int) (_from), G_ip_file.line_no,\ G_ip_file.file_spec);\ vv_exit ();\ }\ else\ {\ _to = G_decode_table[(int) (_from)];\ } /*- **============================================================================ ** ** FUNCTION ** ** decode ** ** DESCRIPTION ** ** [tbs] ** ** VVE O/P O/P Conversion ** Fmt Fmt Func Type ** -------------------------------------------------------------------- ** FIX FIX write_bytes() byte copy, filling records and ** wrapping round record boundaries. ** If necessary, the last O/P record ** will be padded. ** FIX STM write_bytes() byte copy. ** FIX VAR write_bytes() byte copy, filling records to ** maximum length and wrapping data ** round record boundaries. ** ** STM FIX write_bytes() byte, filling records and ** wrapping round record boundaries. ** If necessary, the last O/P record ** will be padded. ** STM STM write_bytes() byte copy ** STM VAR write_bytes() byte copy, filling records to ** maximum length and wrapping data ** round record boundaries. ** ** VAR FIX write_bytes() record byte copy, filling records ** and wrapping round record ** boundaries. If necessary, the last ** O/P record will be padded. ** VAR STM write_bytes() record byte copy ** VAR VAR write_record() record copy, truncating any ** overlong records ** -------------------------------------------------------------------- ** ** INPUT PARAMETERS ** ** [tbs] ** ** OUTPUT PARAMETERS ** ** [tbs] ** ** RETURN VALUE ** ** [tbs] ** **============================================================================ */ #if (ANSI_SYNTAX) void decode (void) #else /* NOT (ANSI_SYNTAX) */ void decode () #endif /* (ANSI_SYNTAX) */ { Int16 bytes_left; SIZE_T idx; Int32 buffer_size; Int16 bytes_decoded; SIZE_T bytes_expected; Int16 decode_state; Int16 hdr_no; char *ip_buf_ptr; Int16 no_bytes_encoded; char *op_buf_ptr; Int16 part_ending; Int32 rec_bytes_left; char *record_buffer; Int32 record_length; char var_rec_size[32]; /*- **------------------------------------------------------------------------ ** **------------------------------------------------------------------------ */ LOGMSG_2 ("\nPart %3d I/P file: %s", G_ippt_no, G_ip_file.file_spec); LOGMSG_2 ("Part %3d starts on line: %ld", G_ippt_no, G_ip_file.line_no); /*- **------------------------------------------------------------------------ ** Allocate space to decode data. If the VVE file contains variable ** length records, the decoded data bytes are accumulated in a buffer ** before being written. ** ** The size of IO_BUFFER_SIZE should be chosen so that most of the ** records received can be accommodated. If an unusually large record is ** encountered, a larger buffer will be allocated on demand. **------------------------------------------------------------------------ */ buffer_size = IO_BUFFER_SIZE; record_buffer = allocate_buffer ((SIZE_T) buffer_size, "record_buffer"); decode_state = DECODE_REC_LEN; op_buf_ptr = record_buffer; /*- **------------------------------------------------------------------------ ** **------------------------------------------------------------------------ */ for (;;) { ip_buf_ptr = rd_next_line ((Int32) IP_BUFFER_SIZE, G_vv_prefix, G_ip_buffer, &G_ip_file, &G_ippart_bytes); if (ip_buf_ptr == NULL) { if (feof (G_ip_file.file_ptr)) { FATALMSG ("premature EOF encountered while decoding"); } else { FATALMSG ("error reading encoded data"); } show_file_context (&G_ip_file, NULL); explain_error (); vv_exit (); } /*- **-------------------------------------------------------------------- ** Decode the byte count character. If it's less than zero, something ** has gone wrong. **-------------------------------------------------------------------- */ DEC_BYTE (ip_buf_ptr[0], no_bytes_encoded); ip_buf_ptr++; if (no_bytes_encoded < 0) { FATALMSG_1 ("invalid encoded byte count (%d)", no_bytes_encoded); show_file_context (&G_ip_file, ip_buf_ptr); vv_exit (); } /*- **-------------------------------------------------------------------- ** If the byte count is zero, we're at the end of this segment. The ** next line must be an 'end' or 'skipfrom' header line. **-------------------------------------------------------------------- */ if (no_bytes_encoded == 0) { ip_buf_ptr = rd_next_line ((Int32) IP_BUFFER_SIZE, G_vv_prefix, G_ip_buffer, &G_ip_file, &G_ippart_bytes); if (ip_buf_ptr == NULL) { FATALMSG ("error reading encoded data"); show_file_context (&G_ip_file, NULL); explain_error (); vv_exit (); } /*- **---------------------------------------------------------------- ** **---------------------------------------------------------------- */ hdr_no = header_type (&G_ip_file, ip_buf_ptr, G_vvehdr); switch (hdr_no) { /*- **------------------------------------------------------------ ** **------------------------------------------------------------ */ case HDR_END: LOGMSG_2 ("Part %3d ends on line: %ld", G_ippt_no, G_ip_file.line_no); return; /*- **------------------------------------------------------------ ** **------------------------------------------------------------ */ case HDR_SKIPTO: if (G_dec_type != VV_DECODING) { FATALMSG_1 ("`%s' header only allowed in VVE files", G_vvehdr[HDR_SKIPTO].h_string); show_file_context (&G_ip_file, ip_buf_ptr); vv_exit (); } parse_header (&G_ip_file, ip_buf_ptr, &G_vvehdr[hdr_no]); sscanf (G_vvehdr[hdr_no].value, "%hd", &part_ending); G_ippt_no++; if (part_ending != G_ippt_no) { FATALMSG_2 ("Unexpected `%s %d'", G_vvehdr[HDR_SKIPTO].h_string, part_ending); show_file_context (&G_ip_file, ip_buf_ptr); vv_exit (); } LOGMSG_2 ("Part %3d ends on line: %ld", part_ending - 1, G_ip_file.line_no); find_next_part (G_ippt_no, &G_ip_file); continue; /*- **------------------------------------------------------------ ** **------------------------------------------------------------ */ default: FATALMSG ("invalid header found"); show_file_context (&G_ip_file, ip_buf_ptr); vv_exit (); } } /*- **-------------------------------------------------------------------- ** Check that there are enough characters in the line. The encoded ** characters are always written in fours. **-------------------------------------------------------------------- */ bytes_expected = (SIZE_T) (4 * ((no_bytes_encoded + 2) / 3)); if (G_eol_marker != NULL) { bytes_expected += strlen (G_eol_marker); } if (strlen (ip_buf_ptr) < bytes_expected) { ERRORMSG_2 ("%d characters expected - %d found", bytes_expected, strlen (ip_buf_ptr)); show_file_context (&G_ip_file, ip_buf_ptr); break; } /*- **-------------------------------------------------------------------- ** **-------------------------------------------------------------------- */ if (G_vv_file.format != FMT_VARIABLE) { /*- **---------------------------------------------------------------- ** The VVE file was encoded in stream or fixed mode, so decode ** this line of bytes and then write them, updating the CRC as we ** go. **---------------------------------------------------------------- */ op_buf_ptr = record_buffer; bytes_left = no_bytes_encoded; while (bytes_left > 0) { bytes_decoded = decode_bytes (bytes_left, ip_buf_ptr, op_buf_ptr); ip_buf_ptr += 4; op_buf_ptr += bytes_decoded; bytes_left -= bytes_decoded; } for (idx = 0; idx < (SIZE_T) no_bytes_encoded; idx++) { UPDATE_CRC32 (G_op_file.crc32, record_buffer[idx]); } /*- **---------------------------------------------------------------- ** If the /TRANSLATE command qualifier was specified, translate ** the bytes read to the destination character set. **---------------------------------------------------------------- */ if (Q_TRANSLATE) { for (idx = 0; idx < (SIZE_T) no_bytes_encoded; idx++) { record_buffer[idx] = (char) G_xlt_table.xlt_tbl[(Byte) record_buffer[idx]]; } } write_bytes ((Int32) no_bytes_encoded, record_buffer, &G_op_file); G_op_file.bytecount += (Int32) no_bytes_encoded; } else { /*- **---------------------------------------------------------------- ** The VVE file contains variable length records which are much ** more difficult to process. ** ** If at the beginning of a record, treat the first two decoded ** bytes as the record length. **---------------------------------------------------------------- */ if (decode_state == DECODE_REC_LEN) { bytes_decoded = decode_bytes (2, ip_buf_ptr, var_rec_size); record_length = 256L * (((Int32) var_rec_size[0]) & 0xff); record_length += (((Int32) var_rec_size[1]) & 0xff); /*- **------------------------------------------------------------ ** **------------------------------------------------------------ */ if ((record_length < 0L) || (record_length > MAX_VV_RECORD_LEN)) { FATALMSG_1 ("invalid record length recorded (%ld)", (Int32) record_length); show_file_context (&G_ip_file, ip_buf_ptr); vv_exit (); } /*- **------------------------------------------------------------ ** If this record is longer than the current buffer size, we ** need to reallocate a larger buffer that most of the ** records received can be accommodated. If an unusually ** large record is encountered, a larger buffer will be ** allocated on demand. **------------------------------------------------------------ */ if (record_length > buffer_size) { record_buffer = (char *) realloc (record_buffer, (SIZE_T) record_length); if (record_buffer == NULL) { FATALMSG_1 ("couldn't reallocate %ld bytes \ for the record buffer", record_length); vv_exit (); } buffer_size = record_length; DEBUG_1 ("decode: reallocated %ld bytes for the \ record buffer", record_length); } /*- **------------------------------------------------------------ ** The buffer is definitely big enough to hold the record, so ** start decoding the encoded bytes into the buffer. ** ** NOTE ** ** We need to discard the first two decoded bytes which ** contain the record length to avoid a full length record ** overflowing the buffer. **------------------------------------------------------------ */ bytes_left = no_bytes_encoded; op_buf_ptr = record_buffer; bytes_decoded = decode_bytes (bytes_left, ip_buf_ptr, op_buf_ptr); ip_buf_ptr += 4; op_buf_ptr[0] = op_buf_ptr[2]; ++op_buf_ptr; bytes_left -= bytes_decoded; /*- **------------------------------------------------------------ ** **------------------------------------------------------------ */ while (bytes_left > 0) { bytes_decoded = decode_bytes (bytes_left, ip_buf_ptr, op_buf_ptr); ip_buf_ptr += 4; op_buf_ptr += bytes_decoded; bytes_left -= bytes_decoded; } decode_state = DECODE_DATA; rec_bytes_left = record_length; no_bytes_encoded -= 2; rec_bytes_left -= (Int32) no_bytes_encoded; } else { /*- **------------------------------------------------------------ ** We're part of the way through a record, so just decode the ** bytes and append the result to the record buffer. **------------------------------------------------------------ */ bytes_left = no_bytes_encoded; while (bytes_left > 0) { bytes_decoded = decode_bytes (bytes_left, ip_buf_ptr, op_buf_ptr); ip_buf_ptr += 4; op_buf_ptr += bytes_decoded; bytes_left -= bytes_decoded; } rec_bytes_left -= (Int32) no_bytes_encoded; } /*- **---------------------------------------------------------------- ** If all of this record has now been read and decoded into ** 'record_buffer', write it to the output file. **---------------------------------------------------------------- */ if (rec_bytes_left <= 0L) { for (idx = 0; idx < (SIZE_T) record_length; idx++) { UPDATE_CRC32 (G_op_file.crc32, record_buffer[idx]); } /*- **------------------------------------------------------------ ** If the /TRANSLATE command qualifier was specified, ** translate the bytes read to the destination character set. **------------------------------------------------------------ */ if (Q_TRANSLATE) { for (idx = 0; idx < (SIZE_T) record_length; idx++) { record_buffer[idx] = (char) G_xlt_table.xlt_tbl[(Byte) record_buffer[idx]]; } } /*- **------------------------------------------------------------ ** **------------------------------------------------------------ */ if (G_op_file.format == FMT_VARIABLE) { write_record (record_length, record_buffer, &G_op_file); } else { write_bytes (record_length, record_buffer, &G_op_file); } decode_state = DECODE_REC_LEN; G_op_file.bytecount += (Int32) record_length; } } } /* end for (;;) */ free (record_buffer); } /* decode */ /*- **============================================================================ ** ** FUNCTION ** ** decode_bytes ** ** DESCRIPTION ** ** [tbs] ** ** INPUT PARAMETERS ** ** [tbs] ** ** OUTPUT PARAMETERS ** ** [tbs] ** ** RETURN VALUE ** ** [tbs] ** **============================================================================ */ #if (ANSI_SYNTAX) Int16 decode_bytes (CONST Int16 bytes_left, CONST char *ip_buf_ptr, char *op_buf_ptr) #else /* NOT (ANSI_SYNTAX) */ Int16 decode_bytes (bytes_left, ip_buf_ptr, op_buf_ptr) CONST Int16 bytes_left; CONST char *ip_buf_ptr; char *op_buf_ptr; #endif /* (ANSI_SYNTAX) */ { register Int16 tmp0; register Int16 tmp1; register Int16 tmp2; register Int16 tmp3; register Int16 c1; register Int16 c2; register Int16 c3; register Int16 bytes_decoded; /*- **------------------------------------------------------------------------ ** **------------------------------------------------------------------------ */ bytes_decoded = 0; if (bytes_left >= 1) { DEC_BYTE (ip_buf_ptr[0], tmp0); DEC_BYTE (ip_buf_ptr[1], tmp1); c1 = (Int16) (tmp0 << 2) | (tmp1 >> 4); op_buf_ptr[0] = (char) c1; ++bytes_decoded; } if (bytes_left >= 2) { DEC_BYTE (ip_buf_ptr[2], tmp2); c2 = (Int16) (tmp1 << 4) | (tmp2 >> 2); op_buf_ptr[1] = (char) c2; ++bytes_decoded; } if (bytes_left >= 3) { DEC_BYTE (ip_buf_ptr[3], tmp3); c3 = (Int16) (tmp2 << 6) | (tmp3); op_buf_ptr[2] = (char) c3; ++bytes_decoded; } return (bytes_decoded); } /* decode_bytes */ /*- **============================================================================ ** ** FUNCTION ** ** find_next_part ** ** DESCRIPTION ** ** [tbs] ** ** NOTE: if every part is in a file of its own there will be an ** overhead of reading each file TWICE before trying to open ** the new file for the next part. ** ** INPUT PARAMETERS ** ** [tbs] ** ** OUTPUT PARAMETERS ** ** [tbs] ** ** RETURN VALUE ** ** [tbs] ** **============================================================================ */ #if (ANSI_SYNTAX) void find_next_part (CONST Int16 part_needed, File_Info *ip_file) #else /* NOT (ANSI_SYNTAX) */ void find_next_part (part_needed, ip_file) CONST Int16 part_needed; File_Info *ip_file; #endif /* (ANSI_SYNTAX) */ { char *buf_ptr; Int16 hdr_no; Int32 start_line_no; Int16 search_pass; /*- **------------------------------------------------------------------------ ** **------------------------------------------------------------------------ */ if (part_needed > MAX_VV_PARTS) { FATALMSG_1 ("maximum number of parts reached (%d)", MAX_VV_PARTS); vv_exit (); } search_pass = 1; start_line_no = ip_file->line_no; /*- **------------------------------------------------------------------------ ** **------------------------------------------------------------------------ */ buf_ptr = rd_next_line ((Int32) IP_BUFFER_SIZE, G_vv_prefix, G_ip_buffer, ip_file, &G_ippart_bytes); for (;;) { if (buf_ptr == NULL) { /*- **---------------------------------------------------------------- ** **---------------------------------------------------------------- */ if (feof (ip_file->file_ptr)) { /*- **------------------------------------------------------------ ** **------------------------------------------------------------ */ if (ip_file->pipe_flag == TRUE) { FATALMSG_1 ("EOF encountered on search pass %d", search_pass); show_file_context (&G_ip_file, NULL); vv_exit (); } else { DEBUG_1 ("find_next_part: EOF encountered on search \ pass %d", search_pass); DEBUG_2 ("find_next_part: Context: line %ld of file `%s'", ip_file->line_no, ip_file->file_spec); } /*- **------------------------------------------------------------ ** **------------------------------------------------------------ */ switch (search_pass) { case 1: DEBUG_1 ("find_next_part: Rewinding file `%s'", ip_file->file_spec); rewind (ip_file->file_ptr); ip_file->line_no = 0; search_pass = 2; buf_ptr = rd_next_line ((Int32) IP_BUFFER_SIZE, G_vv_prefix, G_ip_buffer, ip_file, &G_ippart_bytes); continue; case 3: FATALMSG_2 ("couldn't find part %d in file `%s'", part_needed, ip_file->file_spec); vv_exit (); case 2: default: FATALMSG_1 ("EOF encountered on search pass %d", search_pass); show_file_context (ip_file, NULL); vv_exit (); } } /*- **---------------------------------------------------------------- ** **---------------------------------------------------------------- */ else { FATALMSG ("error reading file"); show_file_context (ip_file, NULL); explain_error (); vv_exit (); } } /*- **-------------------------------------------------------------------- ** If on pass two, avoid redundant re-reading of the lines read on ** pass one. **-------------------------------------------------------------------- */ if ((search_pass == 2) && (ip_file->line_no >= start_line_no)) { DEBUG_2 ("find_next_part: Couldn't find part %d in file `%s'", part_needed, ip_file->file_spec); f_close (ip_file); open_next_part (part_needed, ip_file); search_pass = 3; ip_file->line_no = 0; } /*- **-------------------------------------------------------------------- ** Check whether this line is a header line. The only header lines ** processed are the SKIPFROM and TABLE headers. **-------------------------------------------------------------------- */ hdr_no = header_type (ip_file, buf_ptr, G_vvehdr); /*- **-------------------------------------------------------------------- ** If a SKIPFROM header is encountered and an encoding table was not ** specified on the command line, it is checked to see if it ** corresponds to the start of wanted part. **-------------------------------------------------------------------- */ if (hdr_no == HDR_SKIPFROM) { if (chk_skipfrom (buf_ptr, part_needed, G_hdrf_spec, &G_vvehdr[HDR_SKIPFROM], ip_file) == TRUE) { LOGMSG_2 ("Part %3d starts on line: %ld", part_needed, ip_file->line_no); return; } } /*- **-------------------------------------------------------------------- ** If a TABLE header is encountered and the table contents were not ** specified on the command line, the encoding table is updated. **-------------------------------------------------------------------- */ else if ((!Q_ENCODE) && (hdr_no == HDR_TABLE)) { buf_ptr = parse_enc_tbl (buf_ptr, &G_vvehdr[HDR_TABLE], ip_file); if (buf_ptr == NULL) { FATALMSG ("error reading encoding table"); show_file_context (ip_file, NULL); vv_exit (); } strcpy ((char *) G_encode_table, G_vvehdr[HDR_TABLE].value); continue; } buf_ptr = rd_next_line ((Int32) IP_BUFFER_SIZE, G_vv_prefix, G_ip_buffer, ip_file, &G_ippart_bytes); } } /* find_next_part */ /*- **============================================================================ ** ** FUNCTION ** ** initialize ** ** DESCRIPTION ** ** [tbs] ** ** INPUT PARAMETERS ** ** [tbs] ** ** OUTPUT PARAMETERS ** ** [tbs] ** ** RETURN VALUE ** ** [tbs] ** **============================================================================ */ #if (ANSI_SYNTAX) void initialize (void) #else /* NOT (ANSI_SYNTAX) */ void initialize () #endif /* (ANSI_SYNTAX) */ { char *def_file_name; Boolean status; File_Info xlt_file; /*- **------------------------------------------------------------------------ ** **------------------------------------------------------------------------ */ G_ip_file.line_no = 0; G_ippt_no = 1; /*- **------------------------------------------------------------------------ ** **------------------------------------------------------------------------ */ open_ip_file (&G_cmd_ipfile, &G_ip_file); def_file_name = allocate_buffer ((MAX_PATH + 1), "def_file_name"); (void) split_file_spec (G_ip_file.file_spec, NULL, def_file_name, NULL, NULL); /*- **------------------------------------------------------------------------ ** **------------------------------------------------------------------------ */ if (Q_OVERWRITE) { G_overwrite_flag = OVERWRITE_YES; } else if (G_ip_file.pipe_flag == TRUE) { G_overwrite_flag = OVERWRITE_NO; } else { G_overwrite_flag = OVERWRITE_ASK; } /*- **------------------------------------------------------------------------ ** **------------------------------------------------------------------------ */ open_log_file (&G_cmdqual[CMDQ_LOG], def_file_name, G_overwrite_flag, &G_log_file); /*- **------------------------------------------------------------------------ ** **------------------------------------------------------------------------ */ LOGMSG_3 ("VVdecode %s, %s release (%s)\n", VV_VERSION_STR, VV_IMPLEMENTATION, VV_DATE); LOGMSG_1 ("I/P file: %s", G_ip_file.file_spec); LOGMSG_1 ("Overwrite existing files: %s", (Q_OVERWRITE ? "yes" : "no")); LOGMSG_1 ("Log file: %s", G_log_file.file_spec); /*- **------------------------------------------------------------------------ ** **------------------------------------------------------------------------ */ (void) tz_offset (time ((TIME_T) NULL)); set_decoding_type (&G_cmdqual[CMDQ_UUDECODE], &G_cmdqual[CMDQ_XXDECODE], &G_dec_type, &G_vv_prefix, &G_eol_marker); /*- **------------------------------------------------------------------------ ** **------------------------------------------------------------------------ */ rdfi_headers (G_dec_type, &G_ip_file, G_vvehdr); /*- **------------------------------------------------------------------------ ** **------------------------------------------------------------------------ */ if (G_dec_type == VV_DECODING) { /*- **-------------------------------------------------------------------- ** **-------------------------------------------------------------------- */ getv_decodeversion (&G_vvehdr[HDR_DECODEVERSION], &G_vv_decode_version); if (G_vv_decode_version > (Int16) VV_MAJOR_VERSION_NO) { FATALMSG_2 ("VVdecode version %hd.0 or later is\ required to decode file `%s'\n", G_vv_decode_version, G_ip_file.file_spec); vv_exit (); } /*- **-------------------------------------------------------------------- ** **-------------------------------------------------------------------- */ G_vv_file.file_spec[0] = '\0'; getv_mode (&G_vvehdr[HDR_MODE], G_mode_str, &G_vv_file); getv_format (&G_vvehdr[HDR_FORMAT], G_fmt_str, &G_vv_file); getv_reclen (&G_vvehdr[HDR_RECORDLEN], &G_vv_file); getv_timestamp (&G_vvehdr[HDR_TIMESTAMP], &G_vv_file); } else { G_vv_decode_version = 0; G_vv_file.file_spec[0] = '\0'; G_vv_file.format = FMT_STREAM; G_vv_file.mode = MODE_BINARY; G_vv_file.mod_time = INV_TIMESTAMP; G_vv_file.max_rec_len = INV_RECORD_LEN; G_vv_file.lng_rec_len = INV_RECORD_LEN; } getv_operatingsystem (&G_vvehdr[HDR_OPERATINGSYSTEM], &G_vv_operating_system); getv_characterset (&G_vvehdr[HDR_CHARACTERSET], &G_vv_character_set); LOGMSG_1 ("VVE header file spec: %s", G_hdrf_spec); /*- **------------------------------------------------------------------------ ** **------------------------------------------------------------------------ */ set_enc_tbl (&G_cmdqual[CMDQ_ENCODE], ENCODE_TABLE_LEN, G_encode_table); set_dec_tbl (ENCODE_TABLE_LEN, G_encode_table, DECODE_TABLE_LEN, G_decode_table); /*- **------------------------------------------------------------------------ ** ***CHANGES*** **------------------------------------------------------------------------ */ G_xlt_table.xlt_from = NULL; G_xlt_table.xlt_to = NULL; if ((Q_TRANSLATE) || (STRCMPI (G_vv_character_set, VV_CHARACTERSET) != 0)) { status = choose_xlt_table (&G_cmdqual[CMDQ_TRANSLATE], &G_cmdqual[CMDQ_INDEXFILE], G_vv_character_set, VV_CHARACTERSET, &xlt_file); if (status == TRUE) { set_xlt_tbl (&xlt_file, &G_xlt_table, G_xlthdr); } else { LOGMSG ("\nTranslation performed: none"); } } /*- **------------------------------------------------------------------------ ** **------------------------------------------------------------------------ */ if ((G_xlt_table.xlt_from != NULL) && (G_xlt_table.xlt_to != NULL)) { if (STRCMPI (G_vv_character_set, G_xlt_table.xlt_from) != 0) { WARNMSG_2 ("translation file translates from `%s' to `%s'", G_xlt_table.xlt_from, G_xlt_table.xlt_to); INFOMSG_1 ("VVE file character set is `%s'", G_vv_character_set); } if (STRCMPI (VV_CHARACTERSET, G_xlt_table.xlt_to) != 0) { WARNMSG_2 ("translation file translates from `%s' to `%s'", G_xlt_table.xlt_from, G_xlt_table.xlt_to); INFOMSG_1 ("local character set is `%s'", VV_CHARACTERSET); } } /* if (xlt_file != NULL) */ else { if (STRCMPI (G_vv_character_set, VV_CHARACTERSET) != 0) { WARNMSG_1 ("VVE file character set is `%s'", G_vv_character_set); INFOMSG_1 ("local character set is `%s'", VV_CHARACTERSET); } } /*- **------------------------------------------------------------------------ ** Set the key File_Info parameters, taking into account the file ** parameters and the command line qualifier values. **------------------------------------------------------------------------ */ set_mode (&G_cmdqual[CMDQ_MODE], &G_vv_file, G_mode_str, &G_op_file); set_format (&G_cmdqual[CMDQ_FORMAT], &G_vv_file, G_vv_operating_system, G_fmt_str, &G_op_file); set_record_len (&G_cmdqual[CMDQ_RECORDLEN], &G_vv_file, &G_op_file); set_timestamp (&G_cmdqual[CMDQ_TIMESTAMP], &G_vv_file, &G_op_file); set_pad_char (&G_cmdqual[CMDQ_PADCHAR], &G_op_file, &G_op_padchar); /*- **------------------------------------------------------------------------ ** **------------------------------------------------------------------------ */ open_op_file (&G_cmd_opfile, G_overwrite_flag, G_hdrf_spec, &G_op_file); /*- **------------------------------------------------------------------------ ** **------------------------------------------------------------------------ */ init_crc32_table (CRC32_TABLE_SIZE, CRC32_POLYNOMIAL, G_crc32_table); G_op_file.crc32 = CRC32_MASK; G_op_file.bytecount = 0L; G_ip_file.bytecount = 0L; G_ippart_bytes = 0L; free (def_file_name); } /* initialize */ /*- **============================================================================ ** ** FUNCTION ** ** open_ip_file ** ** DESCRIPTION ** ** [tbs] ** ** INPUT PARAMETERS ** ** [tbs] ** ** OUTPUT PARAMETERS ** ** [tbs] ** ** RETURN VALUE ** ** [tbs] ** **============================================================================ */ #if (ANSI_SYNTAX) void open_ip_file (CONST Qualifier_Struct *ip_qualifier, File_Info *ip_file) #else /* NOT (ANSI_SYNTAX) */ void open_ip_file (ip_qualifier, ip_file) CONST Qualifier_Struct *ip_qualifier; File_Info *ip_file; #endif /* (ANSI_SYNTAX) */ { /*- **------------------------------------------------------------------------ ** **------------------------------------------------------------------------ */ if (ip_qualifier->present != TRUE) { INTERNAL_ERROR ("open_ip_file"); } /*- **------------------------------------------------------------------------ ** **------------------------------------------------------------------------ */ ip_file->file_ptr = (FILE *) NULL; ip_file->mode = MODE_TEXT; ip_file->format = DEF_TEXT_FMT; ip_file->max_rec_len = INV_RECORD_LEN; ip_file->lng_rec_len = INV_RECORD_LEN; /*- **------------------------------------------------------------------------ ** **------------------------------------------------------------------------ */ if (STRCMP (ip_qualifier->value, STDIO_SYMBOL) == 0) { strcpy (ip_file->file_spec, "stdin"); ip_file->file_ptr = stdin; ip_file->pipe_flag = TRUE; } else { strcpy (ip_file->file_spec, ip_qualifier->value); /*- **-------------------------------------------------------------------- ** Apply the default file extension for VVencoded files. **-------------------------------------------------------------------- */ #if (STICKY_DEFAULTS) apply_defaults (NULL, DEF_VV_EXT, ip_file->file_spec); #endif /* (STICKY_DEFAULTS) */ DEBUG_1 ("open_ip_file: opening input file `%s'", ip_file->file_spec); ip_file->file_ptr = f_open_in (ip_file); } /*- **------------------------------------------------------------------------ ** **------------------------------------------------------------------------ */ if (ip_file->file_ptr == (FILE *) NULL) { FATALMSG_1 ("error opening input file `%s'", ip_file->file_spec); vv_exit (); } /*- **------------------------------------------------------------------------ ** **------------------------------------------------------------------------ */ if ((ip_file->pipe_flag == TRUE) || (is_a_file (ip_file) == FALSE)) { DEBUG_1 ("open_ip_file: `%s' is not a regular file", ip_file->file_spec); ip_file->pipe_flag = TRUE; set_pipe_mode (ip_file); } } /* open_ip_file */ /*- **============================================================================ ** ** FUNCTION ** ** open_next_part ** ** DESCRIPTION ** ** [tbs] ** ** INPUT PARAMETERS ** ** [tbs] ** ** OUTPUT PARAMETERS ** ** [tbs] ** ** RETURN VALUE ** ** [tbs] ** **============================================================================ */ #if (ANSI_SYNTAX) void open_next_part (CONST Int16 part_needed, File_Info *ip_file) #else /* NOT (ANSI_SYNTAX) */ void open_next_part (part_needed, ip_file) CONST Int16 part_needed; File_Info *ip_file; #endif /* (ANSI_SYNTAX) */ { char file_ext[MAX_EXT + 1]; char prompt_str[65]; SPRINTF (file_ext, VV_EXT_FMT, part_needed); force_file_ext (file_ext, ip_file->file_spec); if (!file_exists (ip_file->file_spec)) { ERRORMSG_2 ("couldn't find part %d file `%s'", part_needed, ip_file->file_spec); SPRINTF (prompt_str, "Enter file specification for part %d: ", part_needed); prompt_for_string (prompt_str, MAX_PATH, ip_file->file_spec); } /*- **------------------------------------------------------------------------ ** **------------------------------------------------------------------------ */ DEBUG_1 ("open_ip_file: opening input file `%s'", ip_file->file_spec); ip_file->file_ptr = f_open_in (ip_file); if (ip_file->file_ptr == (FILE *) NULL) { FATALMSG_1 ("couldn't open part file `%s'", ip_file->file_spec); vv_exit (); } LOGMSG_2 ("\nPart %3d I/P file: %s", part_needed, ip_file->file_spec); } /* open_next_part */ /*- **============================================================================ ** ** FUNCTION ** ** open_op_file ** ** DESCRIPTION ** ** [tbs] ** ** Cmd VVE STICKY Result ** ------------------------------- ** Y N * Cmd ** Y Y N Cmd ** Y Y Y Cmd + VVE ** N Y * VVE ** N N * Error ** ------------------------------- ** ** Notes: 1. The VVE file specification is checked by legal_filespec() ** and transformed if appropriate. ** 2. 'Cmd + VVE' means that the command line value is used, ** with name/extension components taken from the VVE value if ** STICKY_DEFAULTS has been defined for the implementation. ** ** INPUT PARAMETERS ** ** [tbs] ** ** OUTPUT PARAMETERS ** ** [tbs] ** ** RETURN VALUE ** ** [tbs] ** **============================================================================ */ #if (ANSI_SYNTAX) void open_op_file (CONST Qualifier_Struct *op_qualifier, CONST Int16 overwrite_flag, CONST char *vve_hdr_spec, File_Info *op_file) #else /* NOT (ANSI_SYNTAX) */ void open_op_file (op_qualifier, overwrite_flag, vve_hdr_spec, op_file) CONST Qualifier_Struct *op_qualifier; CONST Int16 overwrite_flag; CONST char *vve_hdr_spec; File_Info *op_file; #endif /* (ANSI_SYNTAX) */ { char *vv_file_name; char *vv_file_ext; char *legal_hdrf_spec; op_file->file_ptr = (FILE *) NULL; legal_hdrf_spec = allocate_buffer ((MAX_PATH + 1), "legal_hdrf_spec"); vv_file_name = allocate_buffer ((MAX_PATH + 1), "vv_file_name"); vv_file_ext = allocate_buffer ((MAX_PATH + 1), "vv_file_ext"); /*- **------------------------------------------------------------------------ ** **------------------------------------------------------------------------ */ if (op_qualifier->present == TRUE) { if (STRCMP (op_qualifier->value, STDIO_SYMBOL) == 0) { op_file->pipe_flag = TRUE; strcpy (op_file->file_spec, "stdout"); op_file->file_ptr = stdout; } /*- **-------------------------------------------------------------------- ** **-------------------------------------------------------------------- */ else { strcpy (op_file->file_spec, op_qualifier->value); #if (STICKY_DEFAULTS) if (VVEH_BEGIN) { strcpy (legal_hdrf_spec, legal_filespec (vve_hdr_spec)); (void) split_file_spec (legal_hdrf_spec, NULL, vv_file_name, vv_file_ext, NULL); apply_defaults (vv_file_name, vv_file_ext, op_file->file_spec); } #endif /* (STICKY_DEFAULTS) */ DEBUG_1 ("open_op_file: opening output file `%s'", op_file->file_spec); op_file->file_ptr = f_open_out (overwrite_flag, op_file); } } /*- **------------------------------------------------------------------------ ** **------------------------------------------------------------------------ */ else if (VVEH_BEGIN) { strcpy (op_file->file_spec, legal_filespec (vve_hdr_spec)); DEBUG_1 ("open_op_file: opening output file `%s'", op_file->file_spec); op_file->file_ptr = f_open_out (overwrite_flag, op_file); } /*- **------------------------------------------------------------------------ ** **------------------------------------------------------------------------ */ else { INTERNAL_ERROR ("open_op_file"); } /*- **------------------------------------------------------------------------ ** **------------------------------------------------------------------------ */ if (op_file->file_ptr == (FILE *) NULL) { FATALMSG_1 ("error opening output file `%s'", op_file->file_spec); vv_exit (); } LOGMSG_1 ("O/P file: %s", op_file->file_spec); /*- **------------------------------------------------------------------------ ** Try to detect whether the output file is actually a character device ** like a comms port. If it is, treat it as a pipe. **------------------------------------------------------------------------ */ if ((op_file->pipe_flag == TRUE) || (is_a_file (op_file) == FALSE)) { DEBUG_1 ("open_op_file: `%s' is not a regular file", op_file->file_spec); op_file->pipe_flag = TRUE; set_pipe_mode (op_file); } free (vv_file_name); free (vv_file_ext); free (legal_hdrf_spec); } /* open_op_file */ /*- **============================================================================ ** ** FUNCTION ** ** parse_enc_tbl ** ** DESCRIPTION ** ** [tbs] ** ** INPUT PARAMETERS ** ** [tbs] ** ** OUTPUT PARAMETERS ** ** [tbs] ** ** RETURN VALUE ** ** [tbs] ** **============================================================================ */ #if (ANSI_SYNTAX) char *parse_enc_tbl (CONST char *line_ptr, Header_Struct *hdr_struct, File_Info *ip_file) #else /* NOT (ANSI_SYNTAX) */ char *parse_enc_tbl (line_ptr, hdr_struct, ip_file) CONST char *line_ptr; Header_Struct *hdr_struct; File_Info *ip_file; #endif /* (ANSI_SYNTAX) */ { char *buf_ptr; char dummy[MAX_IP_LINE_LEN + 1]; char *tmp_ptr; int chars_read; int fields_read; /*- **------------------------------------------------------------------------ ** Allocate enough memory to hold an encoding table **------------------------------------------------------------------------ */ hdr_struct->present = FALSE; tmp_ptr = allocate_buffer ((ENCODE_TABLE_LEN + 1), "tmp_ptr"); fields_read = sscanf (line_ptr, "%*s %[^\n]", dummy); /*- **------------------------------------------------------------------------ ** **------------------------------------------------------------------------ */ if (fields_read == 1) { vstrtrws (dummy); chars_read = strlen (dummy); if (chars_read <= ENCODE_TABLE_LEN) { strcpy (tmp_ptr, dummy); } else { ERRORMSG_1 ("too many characters (%d) in encoding table", chars_read); show_file_context (ip_file, NULL); return (NULL); } } else { *tmp_ptr = '\0'; } /*- **------------------------------------------------------------------------ ** **------------------------------------------------------------------------ */ for (;;) { chars_read = strlen ((char *) tmp_ptr); buf_ptr = rd_next_line ((Int32) IP_BUFFER_SIZE, G_vv_prefix, G_ip_buffer, ip_file, &G_ippart_bytes); if (buf_ptr == NULL) { ERRORMSG ("error reading encoding table"); show_file_context (ip_file, NULL); explain_error (); return (NULL); } /*- **-------------------------------------------------------------------- ** The table is terminated by the next header line encountered. **-------------------------------------------------------------------- */ if (header_type (ip_file, buf_ptr, G_vvehdr) != HDR_UNKNOWN) { break; } chars_read += strlen (buf_ptr); if (chars_read <= ENCODE_TABLE_LEN) { strcat (tmp_ptr, buf_ptr); } else { ERRORMSG_1 ("too many characters (%d) in encoding table", chars_read); show_file_context (ip_file, NULL); return (NULL); } } /*- **------------------------------------------------------------------------ ** **------------------------------------------------------------------------ */ if (strlen (tmp_ptr) != ENCODE_TABLE_LEN) { ERRORMSG_1 ("wrong number of characters (%d) in encoding table", chars_read); show_file_context (ip_file, NULL); return (NULL); } hdr_struct->present = TRUE; hdr_struct->value = tmp_ptr; return (buf_ptr); } /* parse_enc_tbl */ /*- **============================================================================ ** ** FUNCTION ** ** prs_idx_file ** ** DESCRIPTION ** ** [tbs] ** ** INPUT PARAMETERS ** ** xlt_file ** [tbs] ** ** OUTPUT PARAMETERS ** ** [tbs] ** ** RETURN VALUE ** ** TRUE - a candidate translation file was found ** FALSE - a candidate translation file could not be ** identified ** **============================================================================ */ #if (ANSI_SYNTAX) Boolean prs_idx_file (CONST char *from_charset, CONST char *to_charset, File_Info *idx_file, File_Info *xlt_file) #else /* NOT (ANSI_SYNTAX) */ Boolean prs_idx_file (from_charset, to_charset, idx_file, xlt_file) CONST char *from_charset; CONST char *to_charset; File_Info *idx_file; File_Info *xlt_file; #endif /* (ANSI_SYNTAX) */ { char buffer[MAX_IP_LINE_LEN + 1]; Int32 bytes_read; char *comment; int fields_read; char idx_from_charset[MAX_IP_LINE_LEN + 1]; char idx_to_charset[MAX_IP_LINE_LEN + 1]; char idx_xlt_filespec[MAX_IP_LINE_LEN + 1]; Boolean xlt_found; /*- **------------------------------------------------------------------------ ** **------------------------------------------------------------------------ */ idx_file->mode = MODE_TEXT; idx_file->format = DEF_TEXT_FMT; idx_file->max_rec_len = INV_RECORD_LEN; idx_file->lng_rec_len = INV_RECORD_LEN; idx_file->line_no = 0; /*- **------------------------------------------------------------------------ ** **------------------------------------------------------------------------ */ idx_file->file_ptr = f_open_in (idx_file); if (idx_file->file_ptr == (FILE *) NULL) { FATALMSG_1 ("error opening translation index file `%s'", idx_file->file_spec); vv_exit (); } /*- **------------------------------------------------------------------------ ** **------------------------------------------------------------------------ */ xlt_found = FALSE; while (xlt_found != TRUE) { idx_file->line_no++; bytes_read = read_line ((Int32) MAX_IP_LINE_LEN, buffer, idx_file); if (bytes_read < 0) { if (feof (idx_file->file_ptr) != 0) { break; } ERRORMSG ("error reading translation index file"); show_file_context (idx_file, NULL); explain_error (); break; } /*- **-------------------------------------------------------------------- ** **-------------------------------------------------------------------- */ buffer[MAX_IP_LINE_LEN] = (char) '\0'; comment = STRCHR (buffer, IDX_COMMENT_CHAR); if (comment != NULL) { *comment = '\0'; } (void) vstrtrws (buffer); if (strlen (buffer) == 0) { continue; } /*- **-------------------------------------------------------------------- ** **-------------------------------------------------------------------- */ fields_read = sscanf (buffer, "%s %s %s", idx_from_charset, idx_to_charset, idx_xlt_filespec); if (fields_read != 3) { ERRORMSG ("error parsing 3 entries in translation index file"); show_file_context (idx_file, buffer); continue; } DEBUG_4 ("prs_idx_file: %04ld: From: `%s', To: `%s', XLT-file: `%s'", idx_file->line_no, idx_from_charset, idx_to_charset, idx_xlt_filespec); /*- **-------------------------------------------------------------------- ** **-------------------------------------------------------------------- */ if ((STRCMPI (idx_from_charset, from_charset) == 0) && (STRCMPI (idx_to_charset, to_charset) == 0)) { strcpy (xlt_file->file_spec, idx_xlt_filespec); xlt_found = TRUE; } } /* while (ret_status == TRUE) */ f_close (idx_file); return (xlt_found); } /* prs_idx_file */ /*- **============================================================================ ** ** FUNCTION ** ** rdfi_headers ** ** DESCRIPTION ** ** [tbs] ** ** INPUT PARAMETERS ** ** [tbs] ** ** OUTPUT PARAMETERS ** ** [tbs] ** ** RETURN VALUE ** ** [tbs] ** **============================================================================ */ #if (ANSI_SYNTAX) void rdfi_headers (CONST Int16 decoding_type, File_Info *ip_file, Header_Struct *vve_hdr_array) #else /* NOT (ANSI_SYNTAX) */ void rdfi_headers (decoding_type, ip_file, vve_hdr_array) CONST Int16 decoding_type; File_Info *ip_file; Header_Struct *vve_hdr_array; #endif /* (ANSI_SYNTAX) */ { char *buf_ptr; Int16 hdr_no; /*- **------------------------------------------------------------------------ ** **------------------------------------------------------------------------ */ buf_ptr = rd_next_line ((Int32) IP_BUFFER_SIZE, G_vv_prefix, G_ip_buffer, ip_file, &G_ippart_bytes); for (;;) { if (buf_ptr == NULL) { if (feof (ip_file->file_ptr)) { FATALMSG_1 ("EOF encountered before `%s' header", G_vvehdr[HDR_BEGIN].h_string); show_file_context (ip_file, NULL); explain_error (); vv_exit (); } else { FATALMSG ("error reading file headers"); show_file_context (ip_file, NULL); explain_error (); vv_exit (); } } /*- **-------------------------------------------------------------------- ** **-------------------------------------------------------------------- */ hdr_no = header_type (ip_file, buf_ptr, vve_hdr_array); /*- **-------------------------------------------------------------------- ** **-------------------------------------------------------------------- */ if (decoding_type != VV_DECODING) { switch (hdr_no) { case HDR_ATTRBEGIN: case HDR_ATTREND: case HDR_BYTECOUNT: case HDR_CHARACTERSET: case HDR_COMMENT: case HDR_CRC32: case HDR_DECODEVERSION: case HDR_FORMAT: case HDR_MODE: case HDR_OPERATINGSYSTEM: case HDR_RECORDLEN: case HDR_SKIPFROM: case HDR_SKIPTO: case HDR_TIMESTAMP: FATALMSG_1 ("VVcode header `%s' found when UU/XXdecoding", G_vvehdr[hdr_no].h_string); show_file_context (ip_file, buf_ptr); vv_exit (); break; default: break; } } /*- **-------------------------------------------------------------------- ** **-------------------------------------------------------------------- */ switch (hdr_no) { case HDR_UNKNOWN: break; case HDR_BEGIN: if (vve_hdr_array[hdr_no].present == TRUE) { FATALMSG_1 ("header `%s' repeated", vve_hdr_array[hdr_no].h_string); show_file_context (ip_file, buf_ptr); vv_exit (); } parse_begin_header (buf_ptr, ip_file, G_dec_type, &vve_hdr_array[hdr_no], &G_hdrf_spec); return; case HDR_COMMENT: display_comment (ip_file, buf_ptr, &vve_hdr_array[hdr_no]); break; case HDR_CHARACTERSET: case HDR_DECODEVERSION: case HDR_FORMAT: case HDR_MODE: case HDR_OPERATINGSYSTEM: case HDR_RECORDLEN: case HDR_TIMESTAMP: if (vve_hdr_array[hdr_no].present == TRUE) { FATALMSG_1 ("header `%s' repeated", vve_hdr_array[hdr_no].h_string); show_file_context (ip_file, buf_ptr); vv_exit (); } parse_header (ip_file, buf_ptr, &vve_hdr_array[hdr_no]); break; /*- **------------------------------------------------------------ ** After parsing the encoding table, jump to the top of the ** enclosing 'for' loop. **------------------------------------------------------------ */ case HDR_TABLE: buf_ptr = parse_enc_tbl (buf_ptr, &vve_hdr_array[hdr_no], ip_file); if (buf_ptr == NULL) { FATALMSG ("error reading encoding table"); show_file_context (ip_file, NULL); vv_exit (); } continue; case HDR_ATTRBEGIN: case HDR_ATTREND: WARNMSG_1 ("VVE header `%s' not yet supported", vve_hdr_array[hdr_no].h_string); show_file_context (ip_file, buf_ptr); break; case HDR_SKIPFROM: case HDR_SKIPTO: case HDR_END: case HDR_BYTECOUNT: case HDR_CRC32: break; default: INTERNAL_ERROR ("rdfi_headers"); break; } buf_ptr = rd_next_line ((Int32) IP_BUFFER_SIZE, G_vv_prefix, G_ip_buffer, ip_file, &G_ippart_bytes); } } /* rdfi_headers */ /*- **============================================================================ ** ** FUNCTION ** ** rdfi_trailers ** ** DESCRIPTION ** ** [tbs] ** ** INPUT PARAMETERS ** ** [tbs] ** ** OUTPUT PARAMETERS ** ** [tbs] ** ** RETURN VALUE ** ** [tbs] ** **============================================================================ */ #if (ANSI_SYNTAX) void rdfi_trailers (CONST Int16 decoding_type, File_Info *ip_file, File_Info *vve_file, Header_Struct *vve_hdr_array) #else /* NOT (ANSI_SYNTAX) */ void rdfi_trailers (decoding_type, ip_file, vve_file, vve_hdr_array) CONST Int16 decoding_type; File_Info *ip_file; File_Info *vve_file; Header_Struct *vve_hdr_array; #endif /* (ANSI_SYNTAX) */ { char *buf_ptr; int hdr_no; int i; int status; for (i = 0; i < 2; i++) { buf_ptr = rd_next_line ((Int32) IP_BUFFER_SIZE, G_vv_prefix, G_ip_buffer, ip_file, &G_ippart_bytes); if (buf_ptr == NULL) { break; } hdr_no = header_type (ip_file, buf_ptr, vve_hdr_array); /*- **-------------------------------------------------------------------- ** **-------------------------------------------------------------------- */ if (hdr_no == HDR_BYTECOUNT) { if (decoding_type != VV_DECODING) { FATALMSG_1 ("header `%s' not supported when UU/XXdecoding", vve_hdr_array[hdr_no].h_string); vv_exit (); } parse_header (ip_file, buf_ptr, &vve_hdr_array[hdr_no]); status = sscanf (vve_hdr_array[hdr_no].value, "%ld", &(vve_file->bytecount)); if ((status != 1) || (vve_file->bytecount < 0)) { ERRORMSG_1 ("error parsing value of `%s' header", vve_hdr_array[hdr_no].h_string); show_file_context (ip_file, buf_ptr); vve_hdr_array[hdr_no].present = FALSE; } } /*- **-------------------------------------------------------------------- ** **-------------------------------------------------------------------- */ else if (hdr_no == HDR_CRC32) { if (decoding_type != VV_DECODING) { FATALMSG_1 ("header `%s' not supported when UU/XXdecoding", vve_hdr_array[hdr_no].h_string); vv_exit (); } parse_header (ip_file, buf_ptr, &vve_hdr_array[hdr_no]); status = sscanf (vve_hdr_array[hdr_no].value, "%lx", &(vve_file->crc32)); if (status != 1) { ERRORMSG_1 ("error parsing value of `%s' header", vve_hdr_array[hdr_no].h_string); show_file_context (ip_file, buf_ptr); vve_hdr_array[hdr_no].present = FALSE; } } /*- **-------------------------------------------------------------------- ** **-------------------------------------------------------------------- */ else { break; } } } /* rdfi_trailers */ /*- **============================================================================ ** ** FUNCTION ** ** set_decoding_type ** ** DESCRIPTION ** ** [tbs] ** ** INPUT PARAMETERS ** ** [tbs] ** ** OUTPUT PARAMETERS ** ** [tbs] ** ** RETURN VALUE ** ** [tbs] ** **============================================================================ */ #if (ANSI_SYNTAX) void set_decoding_type ( CONST Qualifier_Struct *uu_qualifier, CONST Qualifier_Struct *xx_qualifier, Int16 *decoding_type, char **vve_line_prefix, char **vve_eol_marker) #else /* NOT (ANSI_SYNTAX) */ void set_decoding_type (uu_qualifier, xx_qualifier, decoding_type, vve_line_prefix, vve_eol_marker) CONST Qualifier_Struct *uu_qualifier; CONST Qualifier_Struct *xx_qualifier; Int16 *decoding_type; char **vve_line_prefix; char **vve_eol_marker; #endif /* (ANSI_SYNTAX) */ { /*- **------------------------------------------------------------------------ ** **------------------------------------------------------------------------ */ if (uu_qualifier->present == TRUE) { *decoding_type = UU_DECODING; *vve_line_prefix = NULL; *vve_eol_marker = NULL; LOGMSG ("Decoding method: UUcode\n"); } else if (xx_qualifier->present == TRUE) { *decoding_type = XX_DECODING; *vve_line_prefix = NULL; *vve_eol_marker = NULL; LOGMSG ("Decoding method: XXcode\n"); } else { *decoding_type = VV_DECODING; *vve_line_prefix = STRDUP (VV_PREFIX); *vve_eol_marker = STRDUP (VV_EOL_MARKER); LOGMSG ("Decoding method: VVcode\n"); } } /* set_decoding_type */ /*- **============================================================================ ** ** FUNCTION ** ** set_enc_tbl ** ** DESCRIPTION ** ** [tbs] ** ** INPUT PARAMETERS ** ** [tbs] ** ** OUTPUT PARAMETERS ** ** [tbs] ** ** RETURN VALUE ** ** [tbs] ** **============================================================================ */ #if (ANSI_SYNTAX) void set_enc_tbl (CONST Qualifier_Struct *enc_qualifier, CONST Int16 enc_tbl_len, char *encode_table) #else /* NOT (ANSI_SYNTAX) */ void set_enc_tbl (enc_qualifier, enc_tbl_len, encode_table) CONST Qualifier_Struct *enc_qualifier; CONST Int16 enc_tbl_len; char *encode_table; #endif /* (ANSI_SYNTAX) */ { File_Info enc_file; int status; /*- **------------------------------------------------------------------------ ** **------------------------------------------------------------------------ */ if (enc_qualifier->present == TRUE) { strcpy (enc_file.file_spec, enc_qualifier->value); /*- **-------------------------------------------------------------------- ** If an extension has not been provided, use the default extension ** for encoding table files. **-------------------------------------------------------------------- */ #if (STICKY_DEFAULTS) apply_defaults (NULL, DEF_ENC_EXT, enc_file.file_spec); #endif /* (STICKY_DEFAULTS) */ status = rd_enc_tbl (&enc_file, enc_tbl_len, encode_table); if (!status) { FATALMSG_1 ("error reading encoding table file `%s'", enc_file.file_spec); vv_exit (); } } /*- **------------------------------------------------------------------------ ** **------------------------------------------------------------------------ */ else if (VVEH_TABLE) { strcpy (enc_file.file_spec, G_ip_file.file_spec); strcpy ((char *) encode_table, G_vvehdr[HDR_TABLE].value); } /*- **------------------------------------------------------------------------ ** There's no table in the file, nor one specified on the command ** line, so use the default table for the particular decoding type. **------------------------------------------------------------------------ */ else { switch (G_dec_type) { case UU_DECODING: strcpy (enc_file.file_spec, "default UUcode"); strcpy ((char *) encode_table, UU_ENCODE_TABLE); break; case XX_DECODING: strcpy (enc_file.file_spec, "default XXcode"); strcpy ((char *) encode_table, XX_ENCODE_TABLE); break; case VV_DECODING: default: strcpy (enc_file.file_spec, "default VVcode"); strcpy ((char *) encode_table, VV_ENCODE_TABLE); break; } } /*- **------------------------------------------------------------------------ ** **------------------------------------------------------------------------ */ LOGMSG_1 ("\nEncoding table source: %s", enc_file.file_spec); LOGMSG_1 ("Encoding table contents: %.32s", encode_table); LOGMSG_1 (" %.32s", encode_table + 32); } /* set_enc_tbl */ /*- **============================================================================ ** ** FUNCTION ** ** set_format ** ** DESCRIPTION ** ** Set the format (fixed/stream/variable) to use when writing the output ** file. The format may be set from the command line, VVE file or the ** default specified in machine.h for the file mode. The logic used is: ** ** Cmd OS diff VVE Result ** ------------------------------- ** Y * * Cmd ** N Y * Def ** N N Y VVE ** N N N Def ** ------------------------------- ** ** INPUT PARAMETERS ** ** vve_file - a File_Info structure containing the results of ** parsing the VVE file headers. ** ** INPUT PARAMETERS ** ** [tbs] ** ** OUTPUT PARAMETERS ** ** [tbs] ** ** RETURN VALUE ** ** [tbs] ** **============================================================================ */ #if (ANSI_SYNTAX) void set_format (CONST Qualifier_Struct *fmt_qualifier, CONST File_Info *vve_file, CONST char *vve_os_str, CONST char *fmt_str_array[], File_Info *op_file) #else /* NOT (ANSI_SYNTAX) */ void set_format (fmt_qualifier, vve_file, vve_os_str, fmt_str_array, op_file) CONST Qualifier_Struct *fmt_qualifier; CONST File_Info *vve_file; CONST char *vve_os_str; CONST char *fmt_str_array[]; File_Info *op_file; #endif /* (ANSI_SYNTAX) */ { Int16 cmd_format; /*- **------------------------------------------------------------------------ ** Get the format specified on the command line (if any). **------------------------------------------------------------------------ */ cmd_format = getc_format (fmt_qualifier, fmt_str_array); /*- **------------------------------------------------------------------------ ** IF a valid format was specified on the command line ** THEN use the command line format value. **------------------------------------------------------------------------ */ if (cmd_format != INV_FORMAT) { op_file->format = cmd_format; } /*- **------------------------------------------------------------------------ ** IF a valid format was not specified on the command line ** AND the VVE file was created on a different operating system ** THEN use the default format and issue a warning. **------------------------------------------------------------------------ */ else if (STRCMPI (vve_os_str, VV_OPERATING_SYSTEM) != 0) { WARNMSG_1 ("VVE file created on a different operating system: `%s'", vve_os_str); INFOMSG ("the output file will be created using the default format"); op_file->format = (op_file->mode == MODE_BINARY) ? DEF_BINARY_FMT : DEF_TEXT_FMT; } /*- **------------------------------------------------------------------------ ** IF a valid format was not specified on the command line ** AND the VVE file was created on the same operating system ** AND the VVE file contained a valid format value ** THEN use the VVE format value. **------------------------------------------------------------------------ */ else if ((STRCMPI (vve_os_str, VV_OPERATING_SYSTEM) == 0) && (vve_file->format != INV_FORMAT)) { op_file->format = vve_file->format; } /*- **------------------------------------------------------------------------ ** ELSE use the default format value. **------------------------------------------------------------------------ */ else { op_file->format = (op_file->mode == MODE_BINARY) ? DEF_BINARY_FMT : DEF_TEXT_FMT; } /*- **------------------------------------------------------------------------ ** **------------------------------------------------------------------------ */ switch (op_file->format) { /*- **-------------------------------------------------------------------- ** **-------------------------------------------------------------------- */ case FMT_FIXED: #if (SUPPORT_FIXED_FMT) break; #else /* NOT (SUPPORT_FIXED_FMT) */ WARNMSG_1 ("format `%s' is not supported by this implementation", fmt_str_array[op_file->format]); INFOMSG ("output file will be created using the default format"); op_file->format = (op_file->mode == MODE_BINARY) ? DEF_BINARY_FMT : DEF_TEXT_FMT; break; #endif /* (SUPPORT_FIXED_FMT) */ /*- **-------------------------------------------------------------------- ** **-------------------------------------------------------------------- */ case FMT_STREAM: #if (SUPPORT_STREAM_FMT) break; #else /* NOT (SUPPORT_STREAM_FMT) */ WARNMSG_1 ("format `%s' is not supported by this implementation", fmt_str_array[op_file->format]); INFOMSG ("output file will be created using the default format"); op_file->format = (op_file->mode == MODE_BINARY) ? DEF_BINARY_FMT : DEF_TEXT_FMT; break; #endif /* (SUPPORT_STREAM_FMT) */ /*- **-------------------------------------------------------------------- ** **-------------------------------------------------------------------- */ case FMT_VARIABLE: #if (SUPPORT_VARIABLE_FMT) break; #else /* NOT (SUPPORT_VARIABLE_FMT) */ WARNMSG_1 ("format `%s' is not supported by this implementation", fmt_str_array[op_file->format]); INFOMSG ("output file will be created using the default format"); op_file->format = (op_file->mode == MODE_BINARY) ? DEF_BINARY_FMT : DEF_TEXT_FMT; break; #endif /* (SUPPORT_VARIABLE_FMT) */ default: op_file->format = (op_file->mode == MODE_BINARY) ? DEF_BINARY_FMT : DEF_TEXT_FMT; break; } /*- **------------------------------------------------------------------------ ** **------------------------------------------------------------------------ */ if (op_file->format != INV_FORMAT) { LOGMSG_1 ("O/P file format: %s", fmt_str_array[op_file->format]); } } /* set_format */ /*- **============================================================================ ** ** FUNCTION ** ** set_idx_file ** ** DESCRIPTION ** ** [tbs] ** ** INPUT PARAMETERS ** ** [tbs] ** ** OUTPUT PARAMETERS ** ** [tbs] ** ** RETURN VALUE ** ** [tbs] ** **============================================================================ */ #if (ANSI_SYNTAX) Boolean set_idx_file (CONST Qualifier_Struct *idx_qualifier, File_Info *idx_file) #else /* NOT (ANSI_SYNTAX) */ Boolean set_idx_file (idx_qualifier, idx_file) CONST Qualifier_Struct *idx_qualifier; File_Info *idx_file; #endif /* (ANSI_SYNTAX) */ { char *tmp_ptr; /*- **------------------------------------------------------------------------ ** **------------------------------------------------------------------------ */ if (idx_qualifier->present == TRUE) { strcpy (idx_file->file_spec, idx_qualifier->value); /*- **-------------------------------------------------------------------- ** If an extension has not been provided, use the default extension ** for the translation index file. **-------------------------------------------------------------------- */ #if (STICKY_DEFAULTS) apply_defaults (NULL, DEF_IDX_EXT, idx_file->file_spec); #endif /* (STICKY_DEFAULTS) */ return (TRUE); } tmp_ptr = NULL; /*- **------------------------------------------------------------------------ ** **------------------------------------------------------------------------ */ if ((VV_INDEX_ENVVAR != NULL) && (strlen (VV_INDEX_ENVVAR) > 0)) { tmp_ptr = getenv (VV_INDEX_ENVVAR); if ((tmp_ptr != NULL) && (strlen (tmp_ptr) > 0)) { strcpy (idx_file->file_spec, tmp_ptr); return (TRUE); } } /*- **------------------------------------------------------------------------ ** **------------------------------------------------------------------------ */ if ((tmp_ptr == NULL) && (VV_INDEX_FILE != NULL) && (strlen (VV_INDEX_FILE) > 0) && file_exists (VV_INDEX_FILE)) { strcpy (idx_file->file_spec, VV_INDEX_FILE); return (TRUE); } return (FALSE); } /* set_idx_file */ /*- **============================================================================ ** ** FUNCTION ** ** set_mode ** ** DESCRIPTION ** ** Set the mode (text/binary) to use when reading and encoding the input ** file. The mode may be set from the command line, VVE file or the ** default specified in machine.h. The logic used is: ** ** Cmd VVE Result ** ---------------------- ** Y * Cmd ** N N Def ** N Y VVE ** ---------------------- ** ** INPUT PARAMETERS ** ** vve_file - a structure containing the results of ** parsing the VVE file headers. ** ** OUTPUT PARAMETERS ** ** none ** ** RETURN VALUE ** ** none ** **============================================================================ */ #if (ANSI_SYNTAX) void set_mode (CONST Qualifier_Struct *mode_qualifier, CONST File_Info *vve_file, CONST char *mode_str_array[], File_Info *op_file) #else /* NOT (ANSI_SYNTAX) */ void set_mode (mode_qualifier, vve_file, mode_str_array, op_file) CONST Qualifier_Struct *mode_qualifier; CONST File_Info *vve_file; CONST char *mode_str_array[]; File_Info *op_file; #endif /* (ANSI_SYNTAX) */ { Int16 cmd_mode; /*- **------------------------------------------------------------------------ ** Get the mode specified on the command line (if any). **------------------------------------------------------------------------ */ cmd_mode = getc_mode (mode_qualifier, mode_str_array); if (cmd_mode != INV_MODE) { op_file->mode = cmd_mode; } else if (vve_file->mode != INV_MODE) { op_file->mode = vve_file->mode; } else { op_file->mode = DEF_MODE; } /*- **------------------------------------------------------------------------ ** One final check to make sure that the mode is valid. The mode can only ** come from a validated command line or VVE file value, so it should not ** be wrong. **------------------------------------------------------------------------ */ switch (op_file->mode) { case MODE_BINARY: case MODE_TEXT: break; default: FATALMSG_1 ("invalid file encoding mode set (%d)", op_file->mode); vv_exit (); } LOGMSG_1 ("\nO/P file mode: %s", mode_str_array[op_file->mode]); } /* set_mode */ /*- **============================================================================ ** ** FUNCTION ** ** set_pad_char ** ** DESCRIPTION ** ** [tbs] ** ** INPUT PARAMETERS ** ** [tbs] ** ** OUTPUT PARAMETERS ** ** [tbs] ** ** RETURN VALUE ** ** [tbs] ** **============================================================================ */ #if (ANSI_SYNTAX) void set_pad_char (CONST Qualifier_Struct *pad_qualifier, CONST File_Info *op_file, char *pad_char) #else /* NOT (ANSI_SYNTAX) */ void set_pad_char (pad_qualifier, op_file, pad_char) CONST Qualifier_Struct *pad_qualifier; CONST File_Info *op_file; char *pad_char; #endif /* (ANSI_SYNTAX) */ { int tmp_pad_char; int status; /*- **------------------------------------------------------------------------ ** **------------------------------------------------------------------------ */ if (pad_qualifier->present != TRUE) { DEBUG ("pad character not specified on the command line"); if (op_file->mode == MODE_BINARY) { tmp_pad_char = DEF_BINARY_PADCHAR; } else { tmp_pad_char = DEF_TEXT_PADCHAR; } } else { tmp_pad_char = -1; status = sscanf (pad_qualifier->value, "%d", &tmp_pad_char); if ((status != 1) || (tmp_pad_char < 0) || (tmp_pad_char > 255)) { USAGE ("pad character value must be in the range 0-255"); vv_exit (); } } *pad_char = (char) (tmp_pad_char & 0xff); if (op_file->format == FMT_FIXED) { LOGMSG_2 ("O/P file padding character: %d (0x%02x)", *pad_char, *pad_char); } } /* set_pad_char */ /*- **============================================================================ ** ** FUNCTION ** ** set_record_len ** ** DESCRIPTION ** ** Set the maximum record length to use when writing the output file. ** The record length may be set from the command line, VVE file or the ** the default specified in machine.h. The logic used is: ** ** Cmd VVE Result ** ---------------------- ** Y * Cmd ** N Y VVE ** N N Def ** ---------------------- ** ** INPUT PARAMETERS ** ** [tbs] ** ** OUTPUT PARAMETERS ** ** [tbs] ** ** RETURN VALUE ** ** [tbs] ** **============================================================================ */ #if (ANSI_SYNTAX) void set_record_len ( CONST Qualifier_Struct *rec_qualifier, CONST File_Info *vve_file, File_Info *op_file) #else /* NOT (ANSI_SYNTAX) */ void set_record_len (rec_qualifier, vve_file, op_file) CONST Qualifier_Struct *rec_qualifier; CONST File_Info *vve_file; File_Info *op_file; #endif /* (ANSI_SYNTAX) */ { Int32 cmd_reclen; /*- **------------------------------------------------------------------------ ** Get the record length specified on the command line (if any). **------------------------------------------------------------------------ */ cmd_reclen = getc_reclen (rec_qualifier, op_file); if (cmd_reclen != INV_RECORD_LEN) { op_file->max_rec_len = cmd_reclen; } else if (vve_file->max_rec_len != INV_RECORD_LEN) { op_file->max_rec_len = vve_file->max_rec_len; } else { op_file->max_rec_len = INV_RECORD_LEN; } /*- **------------------------------------------------------------------------ ** One final check to make sure that the maximum record length is valid. ** The record length can only come from a validated command line or VVE ** file value or the default setting, so it should not be wrong. ** There is an exception: the default may be set to INV_RECORD_LEN so that ** f_open_out() will use a default value. **------------------------------------------------------------------------ */ if (op_file->max_rec_len == INV_RECORD_LEN) { return; } if (op_file->format == FMT_VARIABLE) { if ((op_file->max_rec_len < MIN_VARIABLE_RECORD_LEN) || (op_file->max_rec_len > MAX_VARIABLE_RECORD_LEN)) { FATALMSG_1 ("invalid maximum fixed record length set (%ld)", op_file->max_rec_len); vv_exit (); } } else { if (op_file->format == FMT_FIXED) { if ((op_file->max_rec_len < MIN_FIXED_RECORD_LEN) || (op_file->max_rec_len > MAX_FIXED_RECORD_LEN)) { FATALMSG_1 ("invalid maximum variable record length set (%ld)", op_file->max_rec_len); vv_exit (); } } } /*- **------------------------------------------------------------------------ ** Only report the maximum record length if it is meaningful for the file ** format. **------------------------------------------------------------------------ */ if ((op_file->format == FMT_FIXED) || (op_file->format == FMT_VARIABLE)) { LOGMSG_1 ("O/P file maximum record length: %ld", op_file->max_rec_len); } } /* set_record_len */ /*- **============================================================================ ** ** FUNCTION ** ** set_timestamp ** ** DESCRIPTION ** ** Set the timestamp to record in the VVE file. The timestamp may be ** set from the command line or VVE file. The logic used is: ** ** Cmd VVE Result ** ------------------------------ ** Y * Cmd ** N Y ExF ** N N Inv ** ------------------------------ ** ** INPUT PARAMETERS ** ** [tbs] ** ** OUTPUT PARAMETERS ** ** [tbs] ** ** RETURN VALUE ** ** [tbs] ** **============================================================================ */ #if (ANSI_SYNTAX) void set_timestamp ( CONST Qualifier_Struct *time_qualifier, CONST File_Info *vve_file, File_Info *op_file) #else /* NOT (ANSI_SYNTAX) */ void set_timestamp (time_qualifier, vve_file, op_file) CONST Qualifier_Struct *time_qualifier; CONST File_Info *vve_file; File_Info *op_file; #endif /* (ANSI_SYNTAX) */ { TIME_T cmd_timestamp; /*- **------------------------------------------------------------------------ ** Get the timestamp specified on the command line (if any). **------------------------------------------------------------------------ */ cmd_timestamp = getc_timestamp (time_qualifier); if (cmd_timestamp != INV_TIMESTAMP) { op_file->mod_time = cmd_timestamp; } else if (vve_file->mod_time != INV_TIMESTAMP) { op_file->mod_time = vve_file->mod_time; } else { op_file->mod_time = INV_TIMESTAMP; } /*- **------------------------------------------------------------------------ ** **------------------------------------------------------------------------ */ if (op_file->mod_time != INV_TIMESTAMP) { LOGMSG_1 ("O/P file timestamp: %s", vv_timestamp (op_file->mod_time)); } } /* set_timestamp */ /*- **============================================================================ ** ** FUNCTION ** ** terminate ** ** DESCRIPTION ** ** [tbs] ** ** INPUT PARAMETERS ** ** [tbs] ** ** OUTPUT PARAMETERS ** ** [tbs] ** ** RETURN VALUE ** ** [tbs] ** **============================================================================ */ #if (ANSI_SYNTAX) void terminate (void) #else /* NOT (ANSI_SYNTAX) */ void terminate () #endif /* (ANSI_SYNTAX) */ { Boolean file_was_padded; Int32 bytes_to_write; Int32 total_records; Int32 count; G_op_file.crc32 = G_op_file.crc32 ^ CRC32_MASK; G_ip_file.bytecount += G_ippart_bytes; rdfi_trailers (G_dec_type, &G_ip_file, &G_vv_file, G_vvehdr); /*- **------------------------------------------------------------------------ ** **------------------------------------------------------------------------ */ if (Q_INPUT_FILE && (G_ip_file.file_ptr != stdin)) { f_close (&G_ip_file); } /*- **------------------------------------------------------------------------ ** **------------------------------------------------------------------------ */ if ((Q_OUTPUT_FILE || VVEH_BEGIN) && (G_op_file.file_ptr != stdout)) { /*- **-------------------------------------------------------------------- ** If we're writing a fixed format file, pad an incomplete last ** record with the file padding character. **-------------------------------------------------------------------- */ file_was_padded = FALSE; if ((G_op_file.format == FMT_FIXED) && ((G_op_file.bytecount % G_op_file.max_rec_len) != 0L)) { total_records = (G_op_file.bytecount + G_op_file.max_rec_len - 1); total_records /= G_op_file.max_rec_len; bytes_to_write = (total_records * G_op_file.max_rec_len); bytes_to_write -= G_op_file.bytecount; for (count = 0; count < bytes_to_write; count++) { write_bytes (1L, &G_op_padchar, &G_op_file); ++G_op_file.bytecount; } file_was_padded = TRUE; } f_close (&G_op_file); } LOGMSG_1 ("\nTotal bytes read: %ld", G_ip_file.bytecount); LOGMSG_1 ("Total I/P parts read: %d", G_ippt_no); /*- **------------------------------------------------------------------------ ** **------------------------------------------------------------------------ */ if (VVEH_BYTECOUNT) { if (G_vv_file.bytecount == G_op_file.bytecount) { LOGMSG_1 ("Total bytes written: %ld [OK]", G_op_file.bytecount); } else { LOGMSG_1 ("Total bytes written: %ld", G_op_file.bytecount); if (file_was_padded == TRUE) { WARNMSG_2 ("last record was padded with value %d (0x%02x)", G_op_padchar, G_op_padchar); } else { WARNMSG_1 ("file size does not match that recorded [%ld]", G_vv_file.bytecount); } } } else { LOGMSG_1 ("Total bytes written: %ld [not recorded]", G_op_file.bytecount); } /*- **------------------------------------------------------------------------ ** **------------------------------------------------------------------------ */ if (VVEH_CRC32) { if (G_vv_file.crc32 == G_op_file.crc32) { LOGMSG_1 ("CRC-32: %08lx [OK]", G_op_file.crc32); } else { LOGMSG_1 ("CRC-32: %08lx", G_op_file.crc32); WARNMSG_1 ("CRC-32 does not match that recorded [%08lx]", G_vv_file.crc32); } } else { LOGMSG_1 ("CRC-32: %08lx [not recorded]", G_op_file.crc32); } /*- **------------------------------------------------------------------------ ** **------------------------------------------------------------------------ */ if ((G_op_file.pipe_flag != TRUE) && (G_op_file.mod_time != INV_TIMESTAMP)) { set_ftime (&G_op_file); } /*- **------------------------------------------------------------------------ ** **------------------------------------------------------------------------ */ if (Q_LOG && (G_log_file.file_ptr != stderr)) { f_close (&G_log_file); } } /* terminate */ /*- **============================================================================ ** ** FUNCTION ** ** usage_error ** ** DESCRIPTION ** ** [tbs] ** ** INPUT PARAMETERS ** ** [tbs] ** ** OUTPUT PARAMETERS ** ** [tbs] ** ** RETURN VALUE ** ** [tbs] ** **============================================================================ */ #if (ANSI_SYNTAX) void usage_error (CONST char *reason) #else /* NOT (ANSI_SYNTAX) */ void usage_error (reason) CONST char *reason; #endif /* (ANSI_SYNTAX) */ { /*- **------------------------------------------------------------------------ ** Initial error message, followed by Unix style usage message. **------------------------------------------------------------------------ */ FPRINTF (stderr, "\nVVdecode %s, %s release (%s)\n\n", VV_VERSION_STR, VV_IMPLEMENTATION, VV_DATE); FPRINTF (stderr, "VVdecode: %s\n\n", reason); FPRINTF (stderr, "Usage: VVdecode [qualifiers] input_file [output_file]\n\n"); FPRINTF (stderr, " Valid qualifiers are:\n\n"); /*- **------------------------------------------------------------------------ ** qualifier: 'debug' (if support compiled in) **------------------------------------------------------------------------ */ #if (VV_DEBUG_SUPPORT) FPRINTF (stderr, " %.1s%s\n", QUAL_INTRO, G_cmdqual[CMDQ_DEBUG].q_string); #endif /* (VV_DEBUG_SUPPORT) */ /*- **------------------------------------------------------------------------ ** qualifier: 'encoding_table' **------------------------------------------------------------------------ */ FPRINTF (stderr, " %.1s%s%.1sfile-spec\n", QUAL_INTRO, G_cmdqual[CMDQ_ENCODE].q_string, QUAL_SEP); /*- **------------------------------------------------------------------------ ** qualifier: 'format' **------------------------------------------------------------------------ */ FPRINTF (stderr, " %.1s%s%.1sfile-format (formats supported: %s%s%s%s%s%s%s)\n", QUAL_INTRO, G_cmdqual[CMDQ_FORMAT].q_string, QUAL_SEP, G_fmt_str[FMT_DEFAULT], #if (SUPPORT_FIXED_FMT) " ", G_fmt_str[FMT_FIXED], #else /* NOT (SUPPORT_FIXED_FMT) */ "", "", #endif /* (SUPPORT_FIXED_FMT) */ #if (SUPPORT_STREAM_FMT) " ", G_fmt_str[FMT_STREAM], #else /* NOT (SUPPORT_STREAM_FMT) */ "", "", #endif /* (SUPPORT_STREAM_FMT) */ #if (SUPPORT_VARIABLE_FMT) " ", G_fmt_str[FMT_VARIABLE]); #else /* NOT (SUPPORT_VARIABLE_FMT) */ "", ""); #endif /* (SUPPORT_VARIABLE_FMT) */ /*- **------------------------------------------------------------------------ ** qualifiers: 'help', 'index', 'log', 'mode', 'overwrite' **------------------------------------------------------------------------ */ FPRINTF (stderr, " %.1s%s\n", QUAL_INTRO, G_cmdqual[CMDQ_HELP].q_string); FPRINTF (stderr, " %.1s%s%.1sfile-spec\n", QUAL_INTRO, G_cmdqual[CMDQ_INDEXFILE].q_string, QUAL_SEP); FPRINTF (stderr, " %.1s%s[%.1sfile-spec]\n", QUAL_INTRO, G_cmdqual[CMDQ_LOG].q_string, QUAL_SEP); FPRINTF (stderr, " %.1s%s%.1sfile-encoding-mode (modes supported: binary text)\n", QUAL_INTRO, G_cmdqual[CMDQ_MODE].q_string, QUAL_SEP); FPRINTF (stderr, " %.1s%s\n", QUAL_INTRO, G_cmdqual[CMDQ_OVERWRITE].q_string); /*- **------------------------------------------------------------------------ ** qualifiers: 'pad_character', 'record_length', 'timestamp' **------------------------------------------------------------------------ */ FPRINTF (stderr, " %.1s%s%.1sdecimal-char-value\n", QUAL_INTRO, G_cmdqual[CMDQ_PADCHAR].q_string, QUAL_SEP); FPRINTF (stderr, " %.1s%s%.1sbytes\n", QUAL_INTRO, G_cmdqual[CMDQ_RECORDLEN].q_string, QUAL_SEP); FPRINTF (stderr, " %.1s%s[%.1stime]\n", QUAL_INTRO, G_cmdqual[CMDQ_TIMESTAMP].q_string, QUAL_SEP); /*- **------------------------------------------------------------------------ ** qualifiers: 'translation_file', 'uudecode', 'xxdecode' **------------------------------------------------------------------------ */ FPRINTF (stderr, " %.1s%s%.1sfile-spec\n", QUAL_INTRO, G_cmdqual[CMDQ_TRANSLATE].q_string, QUAL_SEP); FPRINTF (stderr, " %.1s%s\n", QUAL_INTRO, G_cmdqual[CMDQ_UUDECODE].q_string); FPRINTF (stderr, " %.1s%s\n\n", QUAL_INTRO, G_cmdqual[CMDQ_XXDECODE].q_string); G_status = FATAL_STATUS; vv_exit (); } /* usage_error */ /*- **============================================================================ ** ** FUNCTION ** ** main ** ** DESCRIPTION ** ** [tbs] ** ** INPUT PARAMETERS ** ** [tbs] ** ** OUTPUT PARAMETERS ** ** [tbs] ** ** RETURN VALUE ** ** [tbs] ** **============================================================================ */ #if (ANSI_SYNTAX) int main (CONST int argc, CONST char *argv[]) #else /* NOT (ANSI_SYNTAX) */ int main (argc, argv) CONST int argc; CONST char *argv[]; #endif /* (ANSI_SYNTAX) */ { SIZE_T bytes_reqd; /*- **------------------------------------------------------------------------ ** Allocate the global message buffer manually since it is used by the ** various MESSAGE_x and DEBUG_x macros. **------------------------------------------------------------------------ */ G_status = LOG_STATUS; bytes_reqd = sizeof (char) * (SIZE_T) MAX_MSG_LEN; G_tmp_msg = (char *) malloc (bytes_reqd); if (G_tmp_msg == NULL) { FPRINTF (stderr, "unable to allocate %ld bytes for buffer `G_tmp_msg'", bytes_reqd); G_status = FATAL_STATUS; vv_exit (); } DEBUG_1 ("main: allocated %ld bytes for buffer `G_tmp_msg'", (Int32) bytes_reqd); /*- **------------------------------------------------------------------------ ** Allocate the other global buffers. **------------------------------------------------------------------------ */ G_ip_buffer = allocate_buffer ((SIZE_T) IP_BUFFER_SIZE, "G_ip_buffer"); G_op_buffer = allocate_buffer ((SIZE_T) OP_BUFFER_SIZE, "G_op_buffer"); /*- **------------------------------------------------------------------------ ** **------------------------------------------------------------------------ */ scan_cmd_line (argc, argv, QUAL_INTRO, QUAL_SEP, G_cmdqual, &G_cmd_ipfile, &G_cmd_opfile); #if (VV_DEBUG_SUPPORT) #else /* NOT (VV_DEBUG_SUPPORT) */ if (Q_DEBUG) { WARNMSG ("Debugging support was not compiled into VVdecode"); } #endif /* (VV_DEBUG_SUPPORT) */ /*- **------------------------------------------------------------------------ ** If the 'help' option was selected, call usage_error() and stop. **------------------------------------------------------------------------ */ if (Q_HELP) { USAGE ("help requested"); } /*- **------------------------------------------------------------------------ ** If the 'debug' option was selected, ensure that the 'log' option is ** selected. **------------------------------------------------------------------------ */ if (Q_DEBUG) { if (!Q_LOG) { G_cmdqual[CMDQ_LOG].present = TRUE; G_cmdqual[CMDQ_LOG].value = NULL; } G_debugging = TRUE; } /*- **------------------------------------------------------------------------ ** **------------------------------------------------------------------------ */ if (!Q_INPUT_FILE) { USAGE ("input file must be specified"); } initialize (); decode (); terminate (); vv_exit (); return (0); } /* main */