diff options
author | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
commit | e0c6872cf40896c7be36b11dcc744620f10adf1d (patch) | |
tree | 60335e10d2f4354b0674ec22d7b53f0f8abee672 /support/vvcode/vvencode.c |
Initial commit
Diffstat (limited to 'support/vvcode/vvencode.c')
-rw-r--r-- | support/vvcode/vvencode.c | 2349 |
1 files changed, 2349 insertions, 0 deletions
diff --git a/support/vvcode/vvencode.c b/support/vvcode/vvencode.c new file mode 100644 index 0000000000..99b8827879 --- /dev/null +++ b/support/vvcode/vvencode.c @@ -0,0 +1,2349 @@ +/*- +****************************************************************************** +****************************************************************************** +** +** ARCHIVE HEADER INFORMATION +** +** @C-file{ +** FILENAME = "vvencode.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 <kempson@tex.ac.uk> +** +** 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 VVENCODE 1 +#define VVCODE_MAIN 1 + +/*- +**---------------------------------------------------------------------------- +** Standard include files +**---------------------------------------------------------------------------- +*/ +#include <stdio.h> + + +/*- +**---------------------------------------------------------------------------- +** Include the machine specific definitions +**---------------------------------------------------------------------------- +*/ +#include "checkos.h" +#include "machine.h" +#include "local.h" +#include "globals.h" +#include "specific.h" +#include "vvutils.h" + + +/*- +**---------------------------------------------------------------------------- +** Forward declarations of functions in this file +**---------------------------------------------------------------------------- +*/ +int main ARGS ((CONST int argc, + CONST char *argv[])); +Int32 enc_line ARGS ((CONST char *ip_buffer, + CONST Int32 num_bytes, + char *op_buffer)); +void encode ARGS ((void)); +void initialize ARGS ((void)); +void open_ip_file ARGS ((CONST Qualifier_Struct *ip_qualifier, + File_Info *ip_file)); +void open_op_file ARGS ((CONST Qualifier_Struct *op_qualifier, + CONST char *def_file_name, + CONST Int16 overwrite_flag, + File_Info *op_file)); +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 *ex_file, + CONST char *fmt_str_array[], + File_Info *ip_file)); +void set_hdr_file_spec ARGS ((CONST Qualifier_Struct *hdr_qualifier, + CONST File_Info *ip_file, + char **hdr_file_spec)); +void set_ip_filespec ARGS ((CONST Qualifier_Struct *ip_qualifier, + File_Info *ip_file)); +void set_mode ARGS ((CONST Qualifier_Struct *mode_qualifier, + CONST File_Info *ex_file, + CONST char *mode_str_array[], + File_Info *ip_file)); +void set_record_len ARGS ((CONST Qualifier_Struct *rec_qualifer, + CONST File_Info *ex_file, + File_Info *ip_file)); +void set_split_size ARGS ((CONST File_Info *op_file, + Qualifier_Struct *split_qualifier, + Int32 *split_size)); +void set_timestamp ARGS ((CONST Qualifier_Struct *time_qualifier, + CONST File_Info *ex_file, + File_Info *ip_file)); +void start_next_op_file ARGS ((CONST Int16 overwrite_flag, + File_Info *op_file, + Int16 *op_part_no)); +void terminate ARGS ((void)); +void usage_error ARGS ((CONST char *reason)); +void wr_headers ARGS ((CONST Int16 part_no)); + + +/*- +**============================================================================ +** +** FUNCTION +** +** encode +** +** DESCRIPTION +** +** Encode the bytes from the input file and write them to the output +** file. +** +** INPUT PARAMETERS +** +** [tbs] +** +** OUTPUT PARAMETERS +** +** [tbs] +** +** RETURN VALUE +** +** [tbs] +** +**============================================================================ +*/ +#if (ANSI_SYNTAX) + void encode (void) +#else /* NOT (ANSI_SYNTAX) */ + void encode () +#endif /* (ANSI_SYNTAX) */ +{ + char *ip_buffer; + char *buf_ptr; + Int32 buffer_size; + Int32 bytes_left; + Int32 bytes_read; + Int32 bytes_to_encode; + Int16 encode_state; + SIZE_T idx; + char tmp_buffer[MAX_ENCODED_BYTES + 2]; + char vv_buffer[2 * MAX_ENCODED_BYTES]; + Int32 vve_line_bytes; + Int32 vve_room_needed; + + /*- + **------------------------------------------------------------------------ + ** If the input file has variable length format records, then allocate + ** a buffer to hold the largest possible record. For fixed or stream + ** format files, allocate a smaller buffer of IO_BUFFER_SIZE bytes. + **------------------------------------------------------------------------ + */ + if (G_ip_file.format == FMT_VARIABLE) + { + buffer_size = (Int32) MAX_VARIABLE_RECORD_LEN; + } + else + { + buffer_size = (Int32) IO_BUFFER_SIZE; + } + ip_buffer = allocate_buffer ((SIZE_T) buffer_size, "ip_buffer"); + + /*- + **------------------------------------------------------------------------ + ** + **------------------------------------------------------------------------ + */ + for (;;) + { + + /*- + **-------------------------------------------------------------------- + ** + **-------------------------------------------------------------------- + */ + if (G_ip_file.format == FMT_VARIABLE) + { + bytes_read = read_record (MAX_VARIABLE_RECORD_LEN, ip_buffer, + &G_ip_file); + if (bytes_read < 0L) + { + break; + } + G_ip_file.bytecount += bytes_read; + DEBUG_2 ("encode: record length = %5ld, total bytes read = %10ld", + bytes_read, G_ip_file.bytecount); + encode_state = ENCODE_REC_LEN; + } + + /*- + **-------------------------------------------------------------------- + ** + **-------------------------------------------------------------------- + */ + else + { + bytes_read = read_bytes ((Int32) MAX_ENCODED_BYTES, ip_buffer, + &G_ip_file); + if (bytes_read <= 0L) + { + break; + } + G_ip_file.bytecount += (long) bytes_read; + } + + /*- + **-------------------------------------------------------------------- + ** 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) bytes_read; idx++) + { + ip_buffer[idx] = + (char) G_xlt_table.xlt_tbl[(Byte) ip_buffer[idx]]; + } + } + + /*- + **-------------------------------------------------------------------- + ** Compute the CRC of the bytes to be encoded in the VVE file. + **-------------------------------------------------------------------- + */ + for (idx = 0; idx < (SIZE_T) bytes_read; idx++) + { + UPDATE_CRC32 (G_ip_file.crc32, ip_buffer[idx]); + } + + /*- + **-------------------------------------------------------------------- + ** Write the remaining bytes in chunks of MAX_ENCODED_BYTES. If the + ** file is in variable length format, each record is likely to have a + ** shorter last line. + **-------------------------------------------------------------------- + */ + bytes_left = bytes_read; + buf_ptr = ip_buffer; + + /*- + **-------------------------------------------------------------------- + ** + **-------------------------------------------------------------------- + */ + while (bytes_left > 0L) + { + + /*- + **---------------------------------------------------------------- + ** + **---------------------------------------------------------------- + */ + if ((G_ip_file.format == FMT_VARIABLE) + && (encode_state == ENCODE_REC_LEN)) + { + bytes_to_encode = MINIMUM (bytes_left, MAX_ENCODED_BYTES - 2); + tmp_buffer[0] = (char) (bytes_read / 256); + tmp_buffer[1] = (char) (bytes_read % 256); + + for (idx = 0; idx < (SIZE_T) bytes_to_encode; idx++) + { + tmp_buffer[2 + idx] = ip_buffer[idx]; + } + vve_line_bytes = enc_line (tmp_buffer, bytes_to_encode + 2, + vv_buffer); + bytes_left -= bytes_to_encode; + buf_ptr += (SIZE_T) bytes_to_encode; + encode_state = ENCODE_DATA; + } + /*- + **---------------------------------------------------------------- + ** + **---------------------------------------------------------------- + */ + else + { + bytes_to_encode = MINIMUM (bytes_left, MAX_ENCODED_BYTES); + vve_line_bytes = enc_line (buf_ptr, bytes_to_encode, + vv_buffer); + bytes_left -= bytes_to_encode; + buf_ptr += (SIZE_T) bytes_to_encode; + } + + /*- + **---------------------------------------------------------------- + ** If a maximum VVE output file size has been specified, check + ** whether this encoded line will cause that maximum size to be + ** exceeded. + **---------------------------------------------------------------- + */ + if (Q_SPLIT) + { + vve_room_needed = vve_line_bytes + TEXT_LINE_OVERHEAD + + VV_POSTAMBLE_LEN; + + if ((G_oppart_bytes + vve_room_needed) >= G_split_size) + { + start_next_op_file (G_overwrite_flag, &G_op_file, + &G_oppt_no); + G_op_file.bytecount += G_oppart_bytes; + G_oppart_bytes = 0L; + wr_headers (G_oppt_no); + } + } + + /*- + **---------------------------------------------------------------- + ** Write the encoded line to the VVE file. + **---------------------------------------------------------------- + */ + VVEOUT (vv_buffer); + } /* while (bytes_left > 0L) */ + } /* for (;;) */ +} /* encode */ + + + + +/*- +**============================================================================ +** +** 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) */ +{ + File_Info ex_file_info; + char *def_file_name; + File_Info xlt_file; + + /*- + **------------------------------------------------------------------------ + ** Set up the input file specification from the command line argument. + ** The 'pipe_flag' structure field is also set up. + **------------------------------------------------------------------------ + */ + set_ip_filespec (&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; + } + + /*- + **------------------------------------------------------------------------ + ** If the 'log' qualifier was specified, open the log file. On systems + ** which use 'STICKY_DEFAULTS', this must be done after the input file + ** specification is known. + **------------------------------------------------------------------------ + */ + open_log_file (&G_cmdqual[CMDQ_LOG], def_file_name, G_overwrite_flag, + &G_log_file); + + /*- + **------------------------------------------------------------------------ + ** + **------------------------------------------------------------------------ + */ + LOGMSG_3 ("VVencode %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); + LOGMSG ("Encoding method: VVcode\n"); + + /*- + **------------------------------------------------------------------------ + ** Ensure that the local timezone offset from GMT is initialized. + **------------------------------------------------------------------------ + */ + (void) tz_offset (time ((TIME_T) NULL)); + + /*- + **------------------------------------------------------------------------ + ** If we're not reading from standard input, attempt to determine the + ** the key file parameters by examining the file. + **------------------------------------------------------------------------ + */ + if (G_ip_file.pipe_flag != TRUE) + { + strcpy (ex_file_info.file_spec, G_ip_file.file_spec); + examine_file (&ex_file_info); + + LOGMSG_1 ("I/P file mode: %s", + (ex_file_info.mode != INV_MODE) ? + (char *) G_mode_str[ex_file_info.mode] : "unknown"); + LOGMSG_1 ("I/P file format: %s", + (ex_file_info.format != INV_FORMAT) ? + (char *) G_fmt_str[ex_file_info.format] : "unknown"); + + if (ex_file_info.lng_rec_len != INV_RECORD_LEN) + { + LOGMSG_1 ("I/P file longest record length: %ld", + ex_file_info.lng_rec_len); + } + else + { + LOGMSG ("I/P file longest record length: unknown"); + } + + if (ex_file_info.max_rec_len != INV_RECORD_LEN) + { + LOGMSG_1 ("I/P file maximum record length: %ld", + ex_file_info.max_rec_len); + } + else + { + LOGMSG ("I/P file maximum record length: unknown"); + } + + LOGMSG_1 ("I/P file timestamp: %s\n", + (ex_file_info.mod_time != INV_TIMESTAMP) ? + vv_timestamp (ex_file_info.mod_time) : "unknown"); + } + + /*- + **------------------------------------------------------------------------ + ** Set the key File_Info parameters, taking into account the file + ** parameters and the command line qualifier values. + **------------------------------------------------------------------------ + */ + set_mode (&G_cmdqual[CMDQ_MODE], &ex_file_info, G_mode_str, &G_ip_file); + set_format (&G_cmdqual[CMDQ_FORMAT], &ex_file_info, G_fmt_str, &G_ip_file); + set_record_len (&G_cmdqual[CMDQ_RECORDLEN], &ex_file_info, &G_ip_file); + set_timestamp (&G_cmdqual[CMDQ_TIMESTAMP], &ex_file_info, &G_ip_file); + + /*- + **------------------------------------------------------------------------ + ** Get and act upon the other command line qualifiers. + **------------------------------------------------------------------------ + */ + set_hdr_file_spec (&G_cmdqual[CMDQ_HDRFILE], &G_ip_file, &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); + + /*- + **------------------------------------------------------------------------ + ** + **------------------------------------------------------------------------ + */ + if (Q_TRANSLATE) + { + strcpy (xlt_file.file_spec, G_cmdqual[CMDQ_TRANSLATE].value); + set_xlt_tbl (&xlt_file, &G_xlt_table, G_xlthdr); + + if (STRCMPI (VV_CHARACTERSET, 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 ("local character set is `%s'", VV_CHARACTERSET); + } + } + else + { + LOGMSG ("Translation performed: none"); + } + + /*- + **------------------------------------------------------------------------ + ** + **------------------------------------------------------------------------ + */ + open_ip_file (&G_cmd_ipfile, &G_ip_file); + + /*- + **------------------------------------------------------------------------ + ** + **------------------------------------------------------------------------ + */ + open_op_file (&G_cmd_opfile, def_file_name, G_overwrite_flag, &G_op_file); + set_split_size (&G_op_file, &G_cmdqual[CMDQ_SPLIT], &G_split_size); + + /*- + **------------------------------------------------------------------------ + ** Initialize global variables. + **------------------------------------------------------------------------ + */ + init_crc32_table (CRC32_TABLE_SIZE, CRC32_POLYNOMIAL, G_crc32_table); + G_ip_file.crc32 = CRC32_MASK; + G_ip_file.bytecount = 0L; + G_op_file.bytecount = 0L; + G_oppart_bytes = 0L; + G_oppt_no = 1; + free (def_file_name); + + /*- + **------------------------------------------------------------------------ + ** Write the VVE file header lines. + **------------------------------------------------------------------------ + */ + wr_headers (G_oppt_no); +} /* 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"); + } + + /*- + **------------------------------------------------------------------------ + ** + **------------------------------------------------------------------------ + */ + if (ip_file->pipe_flag == TRUE) + { + ip_file->file_ptr = stdin; + } + else + { + DEBUG_1 ("encode: 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_op_file +** +** DESCRIPTION +** +** [tbs] +** +** INPUT PARAMETERS +** +** [tbs] +** +** OUTPUT PARAMETERS +** +** [tbs] +** +** RETURN VALUE +** +** [tbs] +** +**============================================================================ +*/ +#if (ANSI_SYNTAX) + void open_op_file (CONST Qualifier_Struct *op_qualifier, + CONST char *def_file_name, + CONST Int16 overwrite_flag, + File_Info *op_file) +#else /* NOT (ANSI_SYNTAX) */ + void open_op_file (op_qualifier, def_file_name, + overwrite_flag, op_file) + CONST Qualifier_Struct *op_qualifier; + CONST char *def_file_name; + CONST Int16 overwrite_flag; + File_Info *op_file; +#endif /* (ANSI_SYNTAX) */ +{ + + /*- + **------------------------------------------------------------------------ + ** + **------------------------------------------------------------------------ + */ + op_file->file_ptr = (FILE *) NULL; + op_file->mode = MODE_TEXT; + op_file->format = DEF_TEXT_FMT; + op_file->max_rec_len = INV_RECORD_LEN; + op_file->lng_rec_len = INV_RECORD_LEN; + + /*- + **------------------------------------------------------------------------ + ** + **------------------------------------------------------------------------ + */ + if (op_qualifier->present == TRUE) + { + + /*- + **-------------------------------------------------------------------- + ** + **-------------------------------------------------------------------- + */ +#if (SUPPORT_PIPING) + if (STRCMP (op_qualifier->value, STDIO_SYMBOL) == 0) + { + op_file->pipe_flag = TRUE; + strcpy (op_file->file_spec, "stdout"); + op_file->file_ptr = stdout; + op_file->format = FMT_STREAM; + } + else +#endif /* (SUPPORT_PIPING) */ + + { + strcpy (op_file->file_spec, op_qualifier->value); + + /*- + **---------------------------------------------------------------- + ** The default file spec for the VVencoded file is the name of the + ** input file with the default extension for VVencoded files. + **---------------------------------------------------------------- + */ +#if (STICKY_DEFAULTS) + apply_defaults (def_file_name, DEF_VV_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 (STDOUT_OUTPUT) + strcpy (op_file->file_spec, "stdout"); + op_file->file_ptr = stdout; + op_file->pipe_flag = TRUE; + +#else /* NOT (STDOUT_OUTPUT) */ + + strcpy (op_file->file_spec, ""); + make_file_spec (NULL, def_file_name, NULL, NULL, op_file->file_spec); + apply_defaults (NULL, DEF_VV_EXT, op_file->file_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); + +#endif /* (STDOUT_OUTPUT) */ + } + + /*- + **------------------------------------------------------------------------ + ** + **------------------------------------------------------------------------ + */ + if (op_file->file_ptr == (FILE *) NULL) + { + FATALMSG_1 ("error opening output file `%s'", op_file->file_spec); + vv_exit (); + } + LOGMSG_1 ("\nVVE O/P file: %s", op_file->file_spec); + + /*- + **------------------------------------------------------------------------ + ** + **------------------------------------------------------------------------ + */ + 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); + } +} /* open_op_file */ + + + +/*- +**============================================================================ +** +** 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 + { + DEBUG ("encoding table not specified on the command line"); + strcpy (enc_file.file_spec, "default VVCODE"); + strcpy ((char *) encode_table, VV_ENCODE_TABLE); + } + + /*- + **------------------------------------------------------------------------ + ** + **------------------------------------------------------------------------ + */ + 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 reading and +** encoding the input file. The format may be set from the command +** line, examine_file() or the default specified in machine.h. The +** logic used is: +** +** Cmd ExFile Pipe Result +** ------------------------------ +** Y * * Cmd +** N N N Def +** N Y N ExF +** N * Y Stm +** ------------------------------ +** +** NOTE: if the input file is standard input, examine_file() is not +** called and stream format is used unless it is overrriden +** from the command line. +** +** INPUT PARAMETERS +** +** [tbs] +** +** OUTPUT PARAMETERS +** +** [tbs] +** +** RETURN VALUE +** +** [tbs] +** +**============================================================================ +*/ +#if (ANSI_SYNTAX) + void set_format (CONST Qualifier_Struct *fmt_qualifier, + CONST File_Info *ex_file, + CONST char *fmt_str_array[], + File_Info *ip_file) +#else /* NOT (ANSI_SYNTAX) */ + void set_format (fmt_qualifier, ex_file, fmt_str_array, + ip_file) + CONST Qualifier_Struct *fmt_qualifier; + CONST File_Info *ex_file; + CONST char *fmt_str_array[]; + File_Info *ip_file; +#endif /* (ANSI_SYNTAX) */ +{ + Int16 cmd_format; + + /*- + **------------------------------------------------------------------------ + ** Get the format specified on the command line (if any). The number of + ** 'if' statements could be reduced by making the second expression more + ** complicated at a cost of less readable code. + **------------------------------------------------------------------------ + */ + cmd_format = getc_format (fmt_qualifier, fmt_str_array); + + if (cmd_format != INV_FORMAT) + { + ip_file->format = cmd_format; + } + else + if (ip_file->pipe_flag == TRUE) + { + ip_file->format = FMT_STREAM; + } + else + if (ex_file->format != INV_FORMAT) + { + ip_file->format = ex_file->format; + } + else + { + if (ip_file->mode == MODE_BINARY) + { + ip_file->format = DEF_BINARY_FMT; + } + else + { + ip_file->format = DEF_TEXT_FMT; + } + } + + /*- + **------------------------------------------------------------------------ + ** + **------------------------------------------------------------------------ + */ + LOGMSG_1 ("VVE encoding format: %s", + (ip_file->format != INV_FORMAT) ? + (char *) fmt_str_array[ip_file->format] : "not recorded"); +} /* set_format */ + + + +/*- +**============================================================================ +** +** FUNCTION +** +** set_hdr_file_spec +** +** DESCRIPTION +** +** [tbs] +** +** INPUT PARAMETERS +** +** [tbs] +** +** OUTPUT PARAMETERS +** +** [tbs] +** +** RETURN VALUE +** +** [tbs] +** +**============================================================================ +*/ +#if (ANSI_SYNTAX) + void set_hdr_file_spec ( + CONST Qualifier_Struct *hdr_qualifier, + CONST File_Info *ip_file, + char **hdr_file_spec) +#else /* NOT (ANSI_SYNTAX) */ + void set_hdr_file_spec (hdr_qualifier, ip_file, + hdr_file_spec) + CONST Qualifier_Struct *hdr_qualifier; + CONST File_Info *ip_file; + char **hdr_file_spec; +#endif /* (ANSI_SYNTAX) */ +{ + char file_name[MAX_NAME + 1]; + char file_ext[MAX_EXT + 1]; + +#if (UPPERCASE_FILESYSTEM) + char *tmp_ptr; +#endif /* (UPPERCASE_FILESYSTEM) */ + + + /*- + **------------------------------------------------------------------------ + ** + **------------------------------------------------------------------------ + */ + *hdr_file_spec = allocate_buffer ((MAX_IP_LINE_LEN + 1), "hdr_file_spec"); + if (hdr_qualifier->present == TRUE) + { + strcpy (*hdr_file_spec, hdr_qualifier->value); + } + else + { + (void) split_file_spec (ip_file->file_spec, NULL, file_name, + file_ext, NULL); + make_file_spec (NULL, file_name, file_ext, NULL, *hdr_file_spec); + +#if (UPPERCASE_FILESYSTEM) + for (tmp_ptr = *hdr_file_spec; *tmp_ptr != '\0'; tmp_ptr++) + { + *tmp_ptr = (char) TOLOWER ((int) *tmp_ptr); + } +#endif /* (UPPERCASE_FILESYSTEM) */ + + } + + /*- + **------------------------------------------------------------------------ + ** + **------------------------------------------------------------------------ + */ + LOGMSG_1 ("VVE header file spec: %s", *hdr_file_spec); +} /* set_hdr_file_spec */ + + + +/*- +**============================================================================ +** +** FUNCTION +** +** set_ip_filespec +** +** DESCRIPTION +** +** [tbs] +** +** INPUT PARAMETERS +** +** [tbs] +** +** OUTPUT PARAMETERS +** +** [tbs] +** +** RETURN VALUE +** +** [tbs] +** +**============================================================================ +*/ +#if (ANSI_SYNTAX) + void set_ip_filespec ( + CONST Qualifier_Struct *ip_qualifier, + File_Info *ip_file) +#else /* NOT (ANSI_SYNTAX) */ + void set_ip_filespec (ip_qualifier, ip_file) + CONST Qualifier_Struct *ip_qualifier; + File_Info *ip_file; +#endif /* (ANSI_SYNTAX) */ +{ + if (ip_qualifier->present != TRUE) + { + INTERNAL_ERROR ("set_ip_filespec"); + } + +#if (SUPPORT_PIPING) + + if (STRCMP (ip_qualifier->value, STDIO_SYMBOL) == 0) + { + strcpy (ip_file->file_spec, "stdin"); + ip_file->pipe_flag = TRUE; + } + else + { + strcpy (ip_file->file_spec, ip_qualifier->value); + } + +#else /* NOT (SUPPORT_PIPING) */ + + strcpy (ip_file->file_spec, ip_qualifier->value); + +#endif /* (SUPPORT_PIPING) */ + +} /* set_ip_filespec */ + + + +/*- +**============================================================================ +** +** 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, examine_file() or +** the default specified in machine.h. The logic used is: +** +** Cmd ExFile Pipe Result +** ------------------------------ +** Y * * Cmd +** N N N Def +** N Y N ExF +** N * Y Def +** ------------------------------ +** +** NOTE: if the input file is standard input, examine_file() is not +** called and the default mode is used unless it is overrriden +** from the command line. +** +** INPUT PARAMETERS +** +** ex_file_info - a File_Info structure containing the results of +** the call to examine_file(). If the input file +** was specified as standard input, this structure +** will not be examined. +** +** OUTPUT PARAMETERS +** +** none +** +** RETURN VALUE +** +** none +** +**============================================================================ +*/ +#if (ANSI_SYNTAX) + void set_mode (CONST Qualifier_Struct *mode_qualifier, + CONST File_Info *ex_file, + CONST char *mode_str_array[], + File_Info *ip_file) +#else /* NOT (ANSI_SYNTAX) */ + void set_mode (mode_qualifier, ex_file, mode_str_array, + ip_file) + CONST Qualifier_Struct *mode_qualifier; + CONST File_Info *ex_file; + CONST char *mode_str_array[]; + File_Info *ip_file; +#endif /* (ANSI_SYNTAX) */ +{ + Int16 cmd_mode; + + /*- + **------------------------------------------------------------------------ + ** Get the mode specified on the command line (if any). The number of + ** 'if' statements could be reduced by making the second expression more + ** complicated at a cost of less readable code. + **------------------------------------------------------------------------ + */ + cmd_mode = getc_mode (mode_qualifier, mode_str_array); + + if (cmd_mode != INV_MODE) + { + ip_file->mode = cmd_mode; + } + else + if (ip_file->pipe_flag == TRUE) + { + ip_file->mode = DEF_MODE; + } + else + if (ex_file->mode != INV_MODE) + { + ip_file->mode = ex_file->mode; + } + else + { + ip_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 value, examine_file() or the default + ** setting, so it should not be wrong. + **------------------------------------------------------------------------ + */ + switch (ip_file->mode) + { + case MODE_BINARY: + case MODE_TEXT: + break; + default: + FATALMSG_1 ("invalid file encoding mode set (%d)", ip_file->mode); + vv_exit (); + } + + /*- + **------------------------------------------------------------------------ + ** + **------------------------------------------------------------------------ + */ + LOGMSG_1 ("VVE encoding mode: %s", + mode_str_array[ip_file->mode]); +} /* set_mode */ + + + +/*- +**============================================================================ +** +** FUNCTION +** +** set_record_len +** +** DESCRIPTION +** +** Set the maximum record length to use when reading and encoding the +** input file. The record length may be set from the command line, +** examine_file() or the default specified in machine.h. The logic used +** is: +** +** Cmd ExFile Pipe Result +** ------------------------------ +** Y * * Cmd +** N N N Def +** N Y N ExF +** N * Y Def +** ------------------------------ +** +** NOTE: if the input file is standard input, examine_file() is not +** called and the default record length is used unless it is +** overrriden from the command line. +** +** INPUT PARAMETERS +** +** [tbs] +** +** OUTPUT PARAMETERS +** +** [tbs] +** +** RETURN VALUE +** +** [tbs] +** +**============================================================================ +*/ +#if (ANSI_SYNTAX) + void set_record_len ( + CONST Qualifier_Struct *rec_qualifier, + CONST File_Info *ex_file, + File_Info *ip_file) +#else /* NOT (ANSI_SYNTAX) */ + void set_record_len (rec_qualifier, ex_file, ip_file) + CONST Qualifier_Struct *rec_qualifier; + CONST File_Info *ex_file; + File_Info *ip_file; +#endif /* (ANSI_SYNTAX) */ +{ + Int32 cmd_reclen; + + /*- + **------------------------------------------------------------------------ + ** Get the record length specified on the command line (if any). The + ** number of 'if' statements could be reduced by making the second + ** expression more complicated at a cost of less readable code. + **------------------------------------------------------------------------ + */ + cmd_reclen = getc_reclen (rec_qualifier, ip_file); + + if (cmd_reclen != INV_RECORD_LEN) + { + ip_file->max_rec_len = cmd_reclen; + ip_file->lng_rec_len = INV_RECORD_LEN; + } + else + if (ip_file->pipe_flag == TRUE) + { + ip_file->max_rec_len = INV_RECORD_LEN; + ip_file->lng_rec_len = INV_RECORD_LEN; + } + else + if (ex_file->max_rec_len != INV_RECORD_LEN) + { + ip_file->max_rec_len = ex_file->max_rec_len; + ip_file->lng_rec_len = ex_file->lng_rec_len; + } + else + { + ip_file->max_rec_len = INV_RECORD_LEN; + ip_file->lng_rec_len = INV_RECORD_LEN; + } + + /*- + **------------------------------------------------------------------------ + ** One final check to make sure that the maximum record length is valid. + ** The longest record length can only come from examine_file() so it + ** should not be wrong. There is an exception: the default may be set to + ** INV_RECORD_LEN so that f_open_in() will use a default value. + **------------------------------------------------------------------------ + */ + if (ip_file->lng_rec_len == INV_RECORD_LEN) + { + LOGMSG ("VVE longest record length: not recorded"); + } + else if (ip_file->format == FMT_VARIABLE) + { + if ((ip_file->lng_rec_len < MIN_VARIABLE_RECORD_LEN) + || (ip_file->lng_rec_len > MAX_VARIABLE_RECORD_LEN)) + { + FATALMSG_1 ("invalid longest record length set (%ld)", + ip_file->lng_rec_len); + vv_exit (); + } + LOGMSG_1 ("VVE longest record length: %ld", + ip_file->lng_rec_len); + } + else if (ip_file->format == FMT_FIXED) + { + if ((ip_file->lng_rec_len < MIN_FIXED_RECORD_LEN) + || (ip_file->lng_rec_len > MAX_FIXED_RECORD_LEN)) + { + FATALMSG_1 ("invalid longest record length set (%ld)", + ip_file->lng_rec_len); + vv_exit (); + } + LOGMSG_1 ("VVE longest record length: %ld", + ip_file->lng_rec_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 value, + ** examine_file() 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_in() will use a default value. + **------------------------------------------------------------------------ + */ + if (ip_file->max_rec_len == INV_RECORD_LEN) + { + LOGMSG ("VVE maximum record length: not recorded"); + } + else if (ip_file->format == FMT_VARIABLE) + { + if ((ip_file->max_rec_len < MIN_VARIABLE_RECORD_LEN) + || (ip_file->max_rec_len > MAX_VARIABLE_RECORD_LEN)) + { + FATALMSG_1 ("invalid maximum record length set (%ld)", + ip_file->max_rec_len); + vv_exit (); + } + LOGMSG_1 ("VVE maximum record length: %ld", + ip_file->max_rec_len); + } + else if (ip_file->format == FMT_FIXED) + { + if ((ip_file->max_rec_len < MIN_FIXED_RECORD_LEN) + || (ip_file->max_rec_len > MAX_FIXED_RECORD_LEN)) + { + FATALMSG_1 ("invalid maximum record length set (%ld)", + ip_file->max_rec_len); + vv_exit (); + } + LOGMSG_1 ("VVE maximum record length: %ld", + ip_file->max_rec_len); + } +} /* set_record_len */ + + + +/*- +**============================================================================ +** +** FUNCTION +** +** set_split_size +** +** DESCRIPTION +** +** [tbs] +** +** INPUT PARAMETERS +** +** [tbs] +** +** OUTPUT PARAMETERS +** +** [tbs] +** +** RETURN VALUE +** +** [tbs] +** +**============================================================================ +*/ +#if (ANSI_SYNTAX) + void set_split_size (CONST File_Info *op_file, + Qualifier_Struct *split_qualifier, + Int32 *split_size) +#else /* NOT (ANSI_SYNTAX) */ + void set_split_size (op_file, split_qualifier, + split_size) + CONST File_Info *op_file; + Qualifier_Struct *split_qualifier; + Int32 *split_size; +#endif /* (ANSI_SYNTAX) */ +{ + Int32 tmp_split_size; + int status; + + if (split_qualifier->present != TRUE) + { + DEBUG ("split size not specified on the command line"); + LOGMSG ("VVE O/P file maximum size: no maximum"); + return; + } + + /*- + **------------------------------------------------------------------------ + ** + **------------------------------------------------------------------------ + */ + if (op_file->pipe_flag == TRUE) + { + split_qualifier->present = FALSE; + WARNMSG ("not encoding to a file - file splitting disabled"); + LOGMSG ("VVE O/P file maximum size: no maximum"); + return; + } + + /*- + **------------------------------------------------------------------------ + ** + **------------------------------------------------------------------------ + */ + tmp_split_size = -1; + status = sscanf (split_qualifier->value, "%ld", &tmp_split_size); + + if ((status != 1) || (tmp_split_size <= 0)) + { + USAGE_1 ("invalid split size specified `%s'", split_qualifier->value); + } + + if (tmp_split_size < (Int32) MIN_SPLIT_SIZE) + { + USAGE_1 ("split size must be at least %ld kB", (Int32) MIN_SPLIT_SIZE); + } + *split_size = tmp_split_size * 1024L; + + /*- + **------------------------------------------------------------------------ + ** + **------------------------------------------------------------------------ + */ + LOGMSG_1 ("VVE O/P file maximum size: %ld kB", tmp_split_size); +} /* set_split_size */ + + + +/*- +**============================================================================ +** +** FUNCTION +** +** set_timestamp +** +** DESCRIPTION +** +** Set the timestamp to record in the VVE file. The timestamp may be +** set from the command line or by examine_file(). The logic used is: +** +** Cmd ExFile Pipe Result +** ------------------------------ +** Y * * Cmd +** N N N Inv +** N Y N ExF +** N * Y Inv +** ------------------------------ +** +** NOTE: if the input file is standard input, examine_file() is not +** called and the timestamp is set to INV_TIMESTAMP unless it is +** overrriden from the command line. +** +** INPUT PARAMETERS +** +** [tbs] +** +** OUTPUT PARAMETERS +** +** [tbs] +** +** RETURN VALUE +** +** [tbs] +** +**============================================================================ +*/ +#if (ANSI_SYNTAX) +void set_timestamp ( + CONST Qualifier_Struct *time_qualifier, + CONST File_Info *ex_file, + File_Info *ip_file) +#else /* NOT (ANSI_SYNTAX) */ + void set_timestamp (time_qualifier, ex_file, ip_file) + CONST Qualifier_Struct *time_qualifier; + CONST File_Info *ex_file; + File_Info *ip_file; +#endif /* (ANSI_SYNTAX) */ +{ + TIME_T cmd_timestamp; + + /*- + **------------------------------------------------------------------------ + ** Get the timestamp specified on the command line (if any). The number + ** of 'if' statements could be reduced by making the second expression + ** more complicated at a cost of less readable code. + **------------------------------------------------------------------------ + */ + cmd_timestamp = getc_timestamp (time_qualifier); + + if (cmd_timestamp != INV_TIMESTAMP) + { + ip_file->mod_time = cmd_timestamp; + } + else + if (ip_file->pipe_flag == TRUE) + { + ip_file->mod_time = INV_TIMESTAMP; + } + else + if (ex_file->mod_time != INV_TIMESTAMP) + { + ip_file->mod_time = ex_file->mod_time; + } + else + { + ip_file->mod_time = INV_TIMESTAMP; + } + + /*- + **------------------------------------------------------------------------ + ** + **------------------------------------------------------------------------ + */ + LOGMSG_1 ("VVE file timestamp: %s", + (ip_file->mod_time != INV_TIMESTAMP) ? + vv_timestamp (ip_file->mod_time) : "not recorded"); +} /* set_timestamp */ + + + +/*- +**============================================================================ +** +** FUNCTION +** +** start_next_op_file +** +** DESCRIPTION +** +** [tbs] +** +** INPUT PARAMETERS +** +** [tbs] +** +** OUTPUT PARAMETERS +** +** [tbs] +** +** RETURN VALUE +** +** [tbs] +** +**============================================================================ +*/ +#if (ANSI_SYNTAX) + void start_next_op_file (CONST Int16 overwrite_flag, + File_Info *op_file, + Int16 *op_part_no) +#else /* NOT (ANSI_SYNTAX) */ + void start_next_op_file (overwrite_flag, op_file, + op_part_no) + CONST Int16 overwrite_flag; + File_Info *op_file; + Int16 *op_part_no; +#endif /* (ANSI_SYNTAX) */ +{ + char next_file_ext[MAX_EXT + 1]; + char tmp_buffer[32]; + + /*- + **------------------------------------------------------------------------ + ** + **------------------------------------------------------------------------ + */ + if (++(*op_part_no) > MAX_VV_PARTS) + { + FATALMSG_1 ("maximum number of parts reached (%d)", MAX_VV_PARTS); + vv_exit (); + } + + /*- + **------------------------------------------------------------------------ + ** + **------------------------------------------------------------------------ + */ + (void) enc_line ("", 0L, tmp_buffer); + VVEOUT (tmp_buffer); + + VVEOUT_2 ("%sskipto %d\n", VV_PREFIX, *op_part_no); + f_close (op_file); + + LOGMSG_2 ("Part %3d bytes written: %ld", + (*op_part_no - 1), G_oppart_bytes); + + /*- + **------------------------------------------------------------------------ + ** + **------------------------------------------------------------------------ + */ + SPRINTF (next_file_ext, VV_EXT_FMT, *op_part_no); + force_file_ext (next_file_ext, op_file->file_spec); + op_file->file_ptr = f_open_out (overwrite_flag, op_file); + + if (op_file->file_ptr == (FILE *) NULL) + { + FATALMSG_1 ("error opening output file `%s'", op_file->file_spec); + vv_exit (); + } +} /* start_next_op_file */ + + + +/*- +**============================================================================ +** +** 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) */ +{ + char tmp_buffer[32]; + + G_ip_file.crc32 = G_ip_file.crc32 ^ CRC32_MASK; + + /*- + **------------------------------------------------------------------------ + ** Write the line of zero encoded bytes to signify the end of encoded + ** data. + **------------------------------------------------------------------------ + */ + (void) enc_line ("", 0L, tmp_buffer); + VVEOUT (tmp_buffer); + + /*- + **------------------------------------------------------------------------ + ** End header. + **------------------------------------------------------------------------ + */ + VVEOUT_2 ("%s%s\n", VV_PREFIX, G_vvehdr[HDR_END].h_string); + + /*- + **------------------------------------------------------------------------ + ** Bytecount header. + **------------------------------------------------------------------------ + */ + VVEOUT_3 ("%s%s %ld\n", VV_PREFIX, + G_vvehdr[HDR_BYTECOUNT].h_string, G_ip_file.bytecount); + + /*- + **------------------------------------------------------------------------ + ** Crc32 header. + **------------------------------------------------------------------------ + */ + VVEOUT_3 ("%s%s %08lx\n", VV_PREFIX, + G_vvehdr[HDR_CRC32].h_string, G_ip_file.crc32); + G_op_file.bytecount += G_oppart_bytes; + LOGMSG_2 ("Part %3d bytes written: %ld", + G_oppt_no, G_oppart_bytes); + + /*- + **------------------------------------------------------------------------ + ** Close the input file if it's not connected to stdin. + **------------------------------------------------------------------------ + */ + if (G_ip_file.file_ptr != stdin) + { + f_close (&G_ip_file); + } + + /*- + **------------------------------------------------------------------------ + ** Close the output file if it's not connected to stdout. + **------------------------------------------------------------------------ + */ + if (G_op_file.file_ptr != stdout) + { + f_close (&G_op_file); + } + + /*- + **------------------------------------------------------------------------ + ** Finish off the log file, then close it if it's not connected to stderr. + **------------------------------------------------------------------------ + */ + LOGMSG_1 ("\nCRC-32: %08lx", G_ip_file.crc32); + LOGMSG_1 ("Total bytes read: %ld", G_ip_file.bytecount); + LOGMSG_1 ("Total bytes written: %ld", G_op_file.bytecount); + LOGMSG_1 ("Total O/P parts written: %d", G_oppt_no); + + if (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, "\nVVencode %s, %s release (%s)\n\n", + VV_VERSION_STR, VV_IMPLEMENTATION, VV_DATE); + FPRINTF (stderr, "VVencode: %s\n\n", reason); + FPRINTF (stderr, + "Usage: VVencode [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)\n", + QUAL_INTRO, G_cmdqual[CMDQ_FORMAT].q_string, QUAL_SEP, + +#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: 'header_filespec', 'help', 'log', 'mode' + **------------------------------------------------------------------------ + */ + FPRINTF (stderr, " %.1s%s%.1sfile-spec\n", + QUAL_INTRO, G_cmdqual[CMDQ_HDRFILE].q_string, QUAL_SEP); + 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_LOG].q_string, QUAL_SEP); + FPRINTF (stderr, " %.1s%s%.1sfile-mode (modes supported: binary text)\n", + QUAL_INTRO, G_cmdqual[CMDQ_MODE].q_string, QUAL_SEP); + + /*- + **------------------------------------------------------------------------ + ** qualifiers: 'overwrite', 'record_length', 'split_size' + **------------------------------------------------------------------------ + */ + FPRINTF (stderr, " %.1s%s\n", + QUAL_INTRO, G_cmdqual[CMDQ_OVERWRITE].q_string); + FPRINTF (stderr, " %.1s%s%.1sbytes\n", + QUAL_INTRO, G_cmdqual[CMDQ_RECORDLEN].q_string, QUAL_SEP); + FPRINTF (stderr, " %.1s%s%.1skbytes\n", + QUAL_INTRO, G_cmdqual[CMDQ_SPLIT].q_string, QUAL_SEP); + + /*- + **------------------------------------------------------------------------ + ** qualifiers: 'timestamp', 'translation_file' + **------------------------------------------------------------------------ + */ + FPRINTF (stderr, " %.1s%s[%.1stime]\n", + QUAL_INTRO, G_cmdqual[CMDQ_TIMESTAMP].q_string, QUAL_SEP); + FPRINTF (stderr, " %.1s%s%.1sfile-spec\n\n", + QUAL_INTRO, G_cmdqual[CMDQ_TRANSLATE].q_string, QUAL_SEP); + + G_status = FATAL_STATUS; + vv_exit (); +} /* usage_error */ + + + +/*- +**============================================================================ +** +** FUNCTION +** +** enc_line +** +** DESCRIPTION +** +** [tbs] +** +** INPUT PARAMETERS +** +** [tbs] +** +** OUTPUT PARAMETERS +** +** [tbs] +** +** RETURN VALUE +** +** [tbs] +** +**============================================================================ +*/ +#if (ANSI_SYNTAX) + Int32 enc_line (CONST char *ip_buffer, + CONST Int32 num_bytes, + char *op_buffer) +#else /* NOT (ANSI_SYNTAX) */ + Int32 enc_line (ip_buffer, num_bytes, op_buffer) + CONST char *ip_buffer; + CONST Int32 num_bytes; + char *op_buffer; +#endif /* (ANSI_SYNTAX) */ +{ + int c1; + int c2; + int c3; + int c4; + SIZE_T idx; + int offset; + + /*- + **------------------------------------------------------------------------ + ** + **------------------------------------------------------------------------ + */ + strcpy (op_buffer, VV_PREFIX); + offset = strlen (op_buffer); + op_buffer[offset++] = ENCODE ((SIZE_T) num_bytes); + + /*- + **------------------------------------------------------------------------ + ** + **------------------------------------------------------------------------ + */ + for (idx = 0; idx < (SIZE_T) num_bytes; idx += 3) + { + c1 = (int) ip_buffer[idx] >> 2; + c2 = (int) ((ip_buffer[idx] << 4) & 0x30) + | ((ip_buffer[idx + 1] >> 4) & 0x0f); + c3 = (int) ((ip_buffer[idx + 1] << 2) & 0x3c) + | ((ip_buffer[idx + 2] >> 6) & 0x03); + c4 = (int) (ip_buffer[idx + 2] & 0x3f); + + op_buffer[offset++] = ENCODE (c1); + op_buffer[offset++] = ENCODE (c2); + op_buffer[offset++] = ENCODE (c3); + op_buffer[offset++] = ENCODE (c4); + } + op_buffer[offset] = '\0'; + strcat (op_buffer, VV_EOL_MARKER); + strcat (op_buffer, "\n"); + return ((Int32) strlen (op_buffer)); +} /* enc_line */ + + + +/*- +**============================================================================ +** +** FUNCTION +** +** wr_headers +** +** DESCRIPTION +** +** [tbs] +** +** INPUT PARAMETERS +** +** [tbs] +** +** OUTPUT PARAMETERS +** +** [tbs] +** +** RETURN VALUE +** +** [tbs] +** +**============================================================================ +*/ +#if (ANSI_SYNTAX) + void wr_headers (CONST Int16 part_no) +#else /* NOT (ANSI_SYNTAX) */ + void wr_headers (part_no) + CONST Int16 part_no; +#endif /* (ANSI_SYNTAX) */ +{ + Int16 adv_line; + + LOGMSG_2 ("\nPart %3d O/P file: %s", + G_oppt_no, G_op_file.file_spec); + LOGMSG_2 ("Part %3d started at I/P byte: %ld", + G_oppt_no, G_ip_file.bytecount); + + /*- + **------------------------------------------------------------------------ + ** Write the VVcode advert text at the top of the VVE file. + **------------------------------------------------------------------------ + */ + for (adv_line = 0; G_vv_advert[adv_line] != NULL; adv_line++) + { + VVEOUT_1 ("%s\n", G_vv_advert[adv_line]); + } + VVEOUT_1 ("Written by VVencode %s,\n", VV_VERSION_STR); + VVEOUT_2 (" %s release (%s)\n", VV_IMPLEMENTATION, VV_DATE); + VVEOUT ("\n"); + + /*- + **------------------------------------------------------------------------ + ** + **------------------------------------------------------------------------ + */ + if (part_no == 1) + { + + /*- + **-------------------------------------------------------------------- + ** VVE header: 'decodeversion' + **-------------------------------------------------------------------- + */ + VVEOUT_3 ("%s%s %d\n", VV_PREFIX, + G_vvehdr[HDR_DECODEVERSION].h_string, VV_MAJOR_VERSION_NO); + + /*- + **-------------------------------------------------------------------- + ** VVE header: 'operating system' + **-------------------------------------------------------------------- + */ + VVEOUT_3 ("%s%s %s\n", VV_PREFIX, + G_vvehdr[HDR_OPERATINGSYSTEM].h_string, VV_OPERATING_SYSTEM); + + /*- + **-------------------------------------------------------------------- + ** VVE header: 'characterset' + ** + ** If the /TRANSLATE qualifier was used, add a 'comment' header + ** recording the original character set (even if it was the same as + ** the translated character set). + **-------------------------------------------------------------------- + */ + if (Q_TRANSLATE) + { + VVEOUT_3 ("%s%s %s\n", VV_PREFIX, + G_vvehdr[HDR_CHARACTERSET].h_string, G_xlt_table.xlt_to); + VVEOUT_3 ("%s%s Original file character set was %s\n", + VV_PREFIX, G_vvehdr[HDR_COMMENT].h_string, + VV_CHARACTERSET); + } + else + { + VVEOUT_3 ("%s%s %s\n", VV_PREFIX, + G_vvehdr[HDR_CHARACTERSET].h_string, VV_CHARACTERSET); + } + + /*- + **-------------------------------------------------------------------- + ** VVE header: 'mode' + **-------------------------------------------------------------------- + */ + VVEOUT_3 ("%s%s %s\n", VV_PREFIX, + G_vvehdr[HDR_MODE].h_string, G_mode_str[G_ip_file.mode]); + + /*- + **-------------------------------------------------------------------- + ** VVE header: 'format' + **-------------------------------------------------------------------- + */ + VVEOUT_3 ("%s%s %s\n", VV_PREFIX, + G_vvehdr[HDR_FORMAT].h_string, G_fmt_str[G_ip_file.format]); + + /*- + **-------------------------------------------------------------------- + ** VVE header: 'recordlength' + ** + ** This header is included only if a valid record length was + ** determined. + **-------------------------------------------------------------------- + */ + if (G_ip_file.max_rec_len != INV_RECORD_LEN) + { + if (G_ip_file.lng_rec_len != INV_RECORD_LEN) + { + VVEOUT_4 ("%s%s %ld %ld\n", VV_PREFIX, + G_vvehdr[HDR_RECORDLEN].h_string, + G_ip_file.max_rec_len, G_ip_file.lng_rec_len); + } + else + { + VVEOUT_3 ("%s%s %ld\n", VV_PREFIX, + G_vvehdr[HDR_RECORDLEN].h_string, + G_ip_file.max_rec_len); + } + } + + /*- + **-------------------------------------------------------------------- + ** VVE header: 'timestamp' + ** + ** This header is included only if a valid timestamp was determined. + **-------------------------------------------------------------------- + */ + if (G_ip_file.mod_time != INV_TIMESTAMP) + { + VVEOUT_3 ("%s%s %s\n", VV_PREFIX, + G_vvehdr[HDR_TIMESTAMP].h_string, + vv_timestamp (G_ip_file.mod_time)); + } + + /*- + **-------------------------------------------------------------------- + ** VVE header: 'table' + ** + ** The 'table' header is followed by the encoding table. + **-------------------------------------------------------------------- + */ + VVEOUT_2 ("%s%s\n", VV_PREFIX, G_vvehdr[HDR_TABLE].h_string); + VVEOUT_2 ("%s%.32s\n", VV_PREFIX, G_encode_table); + VVEOUT_2 ("%s%.32s\n", VV_PREFIX, G_encode_table + 32); + + /*- + **-------------------------------------------------------------------- + ** VVE header: 'begin' + **-------------------------------------------------------------------- + */ + VVEOUT_3 ("%s%s %s\n", VV_PREFIX, + G_vvehdr[HDR_BEGIN].h_string, G_hdrf_spec); + } + else + { + + /*- + **-------------------------------------------------------------------- + ** VVE header: 'table' + ** + ** The 'table' header is followed by the encoding table. + **-------------------------------------------------------------------- + */ + VVEOUT_2 ("%s%s\n", VV_PREFIX, G_vvehdr[HDR_TABLE].h_string); + VVEOUT_2 ("%s%.32s\n", VV_PREFIX, G_encode_table); + VVEOUT_2 ("%s%.32s\n", VV_PREFIX, G_encode_table + 32); + + /*- + **-------------------------------------------------------------------- + ** VVE header: 'skipfrom' + **-------------------------------------------------------------------- + */ + VVEOUT_4 ("%s%s %d %s\n", VV_PREFIX, + G_vvehdr[HDR_SKIPFROM].h_string, G_oppt_no, G_hdrf_spec); + } +} /* wr_headers */ + + + +/*- +**============================================================================ +** +** 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; + + G_status = LOG_STATUS; + G_debugging = FALSE; + + /*- + **------------------------------------------------------------------------ + ** Allocate the global message buffer manually since it is used by the + ** various MESSAGE_x and DEBUG_x macros. + **------------------------------------------------------------------------ + */ + bytes_reqd = sizeof (char) * (SIZE_T) MAX_MSG_LEN; + G_tmp_msg = (char *) malloc (bytes_reqd); + + if (G_tmp_msg == NULL) + { + FPRINTF (stderr, "%s %ld bytes for the message buffer\n", + "FATAL: unable to allocate", bytes_reqd); + + G_status = FATAL_STATUS; + vv_exit (); + } + DEBUG_2 ("main: allocated %ld bytes for buffer `%s'", + (Int32) bytes_reqd, "G_tmp_msg"); + + /*- + **------------------------------------------------------------------------ + ** 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 VVencode"); + } + G_debugging = FALSE; + G_cmdqual[CMDQ_DEBUG].present = FALSE; +#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) + { + G_debugging = TRUE; + if (!Q_LOG) + { + G_cmdqual[CMDQ_LOG].present = TRUE; + G_cmdqual[CMDQ_LOG].value = NULL; + } + } + + /*- + **------------------------------------------------------------------------ + ** + **------------------------------------------------------------------------ + */ + if (!Q_INPUT_FILE) + { + USAGE ("input file must be specified"); + } + + initialize (); + encode (); + terminate (); + + /*- + **------------------------------------------------------------------------ + ** + **------------------------------------------------------------------------ + */ + vv_exit (); + return (0); +} /* main */ |