Subject: MAPPING.C --- a conversion program

From: Rupert Zhu <[email-masked]>
Date: Sat, 1 Jun 91 11:51:29 -0400

This program provides mechanisms to convert ASCII symbols (1 byte) to
their GuoBiao counterparts (2 byte).  It also enables selective
conversion.  That is, you can choose to convert punctuations only,
or numerics only, or English letters only, or any combination of
these options.

-- Rupert Zhu

/********************************************************************
Program:  mapping.c
Translate printable ASCII characters (1 byte) to corresponding
GuoBiao symbols.  Several modes for selective mapping are implemented.
For usage, type  "mapping"  on command line (after compilation).
Author: Rupert Zhu.  May 1/1991.
Revised:  May 6/1991,  May 17/1991.
Send suggestion or bug report to  <[email-masked]>
Plan:  Add a function to remove trailing spaces at end of each line.
********************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define  TRUE       1
#define  FALSE      0

char	*pgname;      /* name of this program  */
int	smart_flag = FALSE;   /*  ????  if on, use smart mapping mode */
int	all_flag = FALSE;     /* if on, map all ASCII char to GuoBiao */
int	digit_flag = FALSE;   /* if on, activate digits mapping  */
int	letter_flag = FALSE;   /* if on, activate mapping of English letters */
int	punct_flag = FALSE;   /* if on, activate punctuations mapping mode */
int	command_flag = FALSE;   /* if on, activate delimiter mapping mode */
int	name_flag = FALSE;  /* indicate whether a file_name is provided */
int	map_count = 0;  /*  no. of ASCII char mapped (i.e., translated)  */
int	error_count = 0;  /* no. of possible errors in smart_mapping mode */
long	char_count = 0;     /* for smart quote mapping */
int	line_count = 0;  /*  total no. of <LF> in output file   */
char in_name[81];     /* input file name (with extension) */
char out_name[81];    /* output file name (with extension .gb0) */
char name[81];        /* file name (without extension */
FILE *in_file;
FILE *out_file;

void usage();
void open_file();
void general_mapping();
void escape();
void quote_mapping();
void message();

void usage()
{
fprintf(stderr, "|--------------------------------------------------------|\n");
fprintf(stderr, "| Usage:  mapping [-a] [-l] [-d] [-p] [-c] file_name     |\n");
fprintf(stderr, "|    Default:        Only map spaces                     |\n");
fprintf(stderr, "|    Option -digit:  activate mapping of digits          |\n");
fprintf(stderr, "|    Option -letter: activate mapping of letters         |\n");
fprintf(stderr, "|    Option -punct:  activate mapping of punctuations    |\n");
fprintf(stderr, "|    Option -all:    equivalent to -digit -letter -punct |\n");
fprintf(stderr, "|              i.e., complete ASCII --> GuoBiao mapping  |\n");
fprintf(stderr, "|    Option -command: activate command delimiter mapping |\n");
fprintf(stderr, "|    Output =  file_name.map                             |\n");
fprintf(stderr, "| Example 1:   mapping  testfile                         |\n");
fprintf(stderr, "|     Map ASCII space to GuoBiao space                   |\n");
fprintf(stderr, "| Example 2:   mapping  -digit -punct  testfile          |\n");
fprintf(stderr, "|     Map ASCII characters except English letters        |\n");
fprintf(stderr, "| Example 3:   mapping  -all  testfile                   |\n");
fprintf(stderr, "|     Map all ASCII characters to GuoBiao characters     |\n");
fprintf(stderr, "|--------------------------------------------------------|\n");
exit(1);
}

/* this does overall control on mapping  */
void general_mapping()
{
	int	b;
	unsigned	c;

	if (all_flag) {
		digit_flag = TRUE;
		letter_flag = TRUE;
		punct_flag = TRUE;
	}
	while ( ( b=fgetc(in_file) ) != EOF) {
		c = (unsigned) b;
		char_count ++;
		if ( c == '^' ) {    /*  escape for special symbols  */
			map_count ++;
			escape();
			continue;
		}
		if (!command_flag && (c=='\\' || c=='{' || c=='}' ) ) {
			/* delimiter for commands */
			fputc(c, out_file);
		}
		else if ( c == '$' && punct_flag ) {
			map_count ++;
			fprintf(out_file, "%c%c", 0xA1, 0xE7);
		}
		else if ( c == '\"' && punct_flag ) {    /* a double quote */
			map_count ++;
			quote_mapping();
		}
		else if ( c == ' ' ) {
			map_count ++;
			fprintf(out_file, "%c%c", 0xA1, 0xA1);
		}
		else if ( ( isalpha(c) && letter_flag )  ||
			  ( isdigit(c) && digit_flag )  ||
			  ( ispunct(c) && punct_flag ) ) {
			map_count ++;
			fprintf(out_file, "%c%c", 0xA3, c+0x80);
		}
		else {
			fputc(c, out_file);

		}
	}
}

/* For editor's convenience, common Chinese puncts can be typed with
   escape symbol  ^   */
void escape()
{
	int	c;

	c = fgetc(in_file);
	if ( c == '[' )
		fprintf(out_file, "%c%c", 0xA1, 0xBE);
	else if ( c == ']' )
		fprintf(out_file, "%c%c", 0xA1, 0xBF);
	else if ( c == '<' )
		fprintf(out_file, "%c%c", 0xA1, 0xB6);
	else if ( c == '>' )
		fprintf(out_file, "%c%c", 0xA1, 0xB7);
	else if ( c == ',' )
		fprintf(out_file, "%c%c", 0xA1, 0xA2);
	else if ( c == '.' )
		fprintf(out_file, "%c%c", 0xA1, 0xA3);
	else
		fprintf(stderr, "Escape symbol not understandable\n");
}

void quote_mapping(void)
{
	static int	quote_even = TRUE;

	quote_even = !quote_even;
	if ( !quote_even ) {   /* left quote */
		char_count = 0;
		fprintf(out_file, "%c%c", 0xA1, 0xB0);
	}
	else if ( char_count <=2000 ) { /* right quote */
		fprintf(out_file, "%c%c", 0xA1, 0xB1);
	}
	else {  /* left quote unmatched, start a new pair */
		char_count = 0;
		fprintf(out_file, "%c%c", 0xA1, 0xB0);
		quote_even = FALSE;
		error_count ++;
		fprintf(stderr, "Un-matched left quote\n");
	}
}

void open_file()
{
	if (name_flag) {
		if ((in_file=fopen(in_name, "rb")) == NULL)
			usage();
		if ((out_file=fopen(out_name,"wb")) == NULL) {
			fprintf(stderr, "Cannot open out_file");
			exit(1);
		}
	}
}

/* report to user what is done */
void message()
{
	fprintf(stderr, "\t|--------------------------------------|\n");
	fprintf(stderr, "\t| Input_file  =  %-16.15s      |\n", in_name);
	fprintf(stderr, "\t| Output_file =  %-16.15s      |\n", out_name);
	fprintf(stderr, "\t| ASCII char translated      =  %4d   |\n",
	map_count);
	fprintf(stderr, "\t| Possible mis-translations  =  %4d   |\n",
	error_count);
	fprintf(stderr, "\t| Job Well Done !                      |\n");
	fprintf(stderr, "\t|--------------------------------------|\n");
}

main(argc, argv)
int argc; char *argv[];
{
	int	i;
	char	*cp;

	pgname = argv[0];
	in_file = NULL;
	out_file = NULL;
	for (i=1; i<argc; i++) {
		cp = argv[i];
		if (*cp == '-') {  /* a flag */
			if (*++cp == 'l') {   /* activate letter mapping */
				letter_flag++;
			}
			else if ( *cp == 'd' ) { /* activate digit mapping */
				digit_flag ++;
			}
			else if ( *cp == 'p' ) { /* activate punct mapping */
				punct_flag ++;
			}
			else if ( *cp == 'a' ) { /* activate all mapping */
				all_flag ++;
			}
			else if ( *cp == 'c' ) {/* activate delimiter mapping */
				command_flag ++;
			}
		}
		else {         /* a file name argument */
			if ( name_flag == TRUE )
				usage();
			name_flag = TRUE;
			strcpy(in_name, cp);
			sscanf(in_name, "%[^.]", name);
			strcpy(out_name, "");   /* initialization */
			strcat(out_name, name);
			strcat(out_name, ".map");   /* use extension .map */
		}
	}
	if ( !name_flag )         /* error: no name is specified */
		usage();
	else {        /* smart mode is specified */
		open_file();
		general_mapping();
		message();
	}
}

/* This is written in standard C, instead of ANSI C, for maximum
   portability.  (Some old C compilers do not know ANSI C yet.)  */