/*- ****************************************************************************** ****************************************************************************** ** ** 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 ** ** 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 /*- **---------------------------------------------------------------------------- ** 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 */