[comp.lang.c] Trigraph programs.

flaps@dgp.toronto.edu (Alan J Rosenthal) (06/07/88)

I wrote these routines before seeing Richard O'Keefe's, but I decided
to post them anyway because I think they're a little more complete.
There is a program to warn about trigraphs, one to trigraph-ize,
another to de-trigraph-ize.

I am placing them in the public domain.  If your compiler doesn't have
options to do these functions, distribute these programs or ones like
them with your compiler.

ajr


This is the LAST posting that should be missing my .signature:
--
- Any questions?
- Well, I thought I had some questions, but they turned out to be a trigraph.
--


#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	tri.c
#	untri.c
#	warnt.c
# This archive created: Mon Jun  6 22:58:59 1988
# By:	Alan J Rosenthal (University of Toronto)
export PATH; PATH=/bin:$PATH
if test -f 'tri.c'
then
	echo shar: will not over-write existing file "'tri.c'"
else
cat << \SHAR_EOF > 'tri.c'
/*
 * tri.c - convert everything in sight to trigraphs.
 *
 * If you have index() instead of strchr(), compile with -Dstrchr=index.
 *
 * The #ifdef unix lines just provide better arg checking.
 *
 * Alan J Rosenthal <flaps@gpu.utcs.toronto.edu>, 2 June 1988.
 */

#include <stdio.h>
#ifdef unix
#include <sys/types.h>
#include <sys/stat.h>
#endif
#define TRUE	1
#define FALSE	0
#define SUCCESS	0
#define FAILURE	(-1)
#define STREQ(s,t)(*(s) == *(t) && strcmp((s),(t)) == 0)

char *progname;


main(argc,argv)
    int argc;
    char **argv;
{
    int status;
    FILE *in,*fopen();
#ifdef unix
    struct stat statbuf;
#endif

    progname = argv[0];

    status = 0;
    if(argc < 1) /* only some systems */ {
	fprintf(stderr,"usage: %s [file ...]\n",progname);
	exit(1);
    } else if(argc == 1) {
	status += process(stdin,"stdin");
    } else {
	while(--argc > 0) {
	    argv++;
	    if(STREQ(*argv,"-")) {
		status += process(stdin,"-");
	    } else {
		if((in = fopen(*argv,"r"))) {
#ifdef unix
		    if(fstat(fileno(in),&statbuf) != 0) {
			/* shouldn't happen */
			fprintf(stderr,"%s: can't fstat\n",*argv);
			exit(1);
		    }
		    if((statbuf.st_mode & S_IFMT) == S_IFDIR) {
			fprintf(stderr,"%s is a directory!\n",*argv);
			status++;
		    } else {
			status += process(in,*argv);
		    }
#else
		    status += process(in,*argv);
#endif
		    (void)fclose(in);
		} else {
		    perror(*argv);
		}
	    }
	}
    }
    exit(status);
}


/* process - process input file */
int process(fp,name)
    FILE *fp;
    char *name;
{
    char buf[300],*p,*trip;
    static char triable[] =  "#[\\]^{|}~";  /* the lining up is suboptimal.. */
    static char trigraph[] = "=(/)\'<!>-";
    extern char *fgets(),*strchr();
    extern void movedown();

    while(fgets(buf,100,fp)) {
	for(trip = triable; *trip; trip++) {
	    while((p = strchr(buf,*trip))) {
		movedown(p,2);
		p[0] = p[1] = '?';
		p[2] = trigraph[trip - triable];
	    }
	}
	fputs(buf,stdout);
    }

    return(0);
}


void movedown(s,count)
    char *s;
    int count;
{
    int i;

    for(i = strlen(s); i >= 0; i--)
	s[i+count] = s[i];
}
SHAR_EOF
if test 2112 -ne "`wc -c < 'tri.c'`"
then
	echo shar: error transmitting "'tri.c'" '(should have been 2112 characters)'
fi
fi # end of overwriting check
if test -f 'untri.c'
then
	echo shar: will not over-write existing file "'untri.c'"
else
cat << \SHAR_EOF > 'untri.c'
/*
 * untri.c - convert trigraphs to the previously standard C character set.
 *
 * If you have index() instead of strchr(), compile with -Dstrchr=index.
 *
 * The #ifdef unix lines just provide better arg checking.
 *
 * Alan J Rosenthal <flaps@gpu.utcs.toronto.edu>, 2 June 1988.
 */

#include <stdio.h>
#ifdef unix
#include <sys/types.h>
#include <sys/stat.h>
#endif
#define TRUE	1
#define FALSE	0
#define SUCCESS	0
#define FAILURE	(-1)
#define STREQ(s,t)(*(s) == *(t) && strcmp((s),(t)) == 0)

char *progname;


main(argc,argv)
    int argc;
    char **argv;
{
    int status;
    FILE *in,*fopen();
#ifdef unix
    struct stat statbuf;
#endif

    progname = argv[0];

    status = 0;
    if(argc < 1) /* only some systems */ {
	fprintf(stderr,"usage: %s [file ...]\n",progname);
	exit(1);
    } else if(argc == 1) {
	status += process(stdin,"stdin");
    } else {
	while(--argc > 0) {
	    argv++;
	    if(STREQ(*argv,"-")) {
		status += process(stdin,"-");
	    } else {
		if((in = fopen(*argv,"r"))) {
#ifdef unix
		    if(fstat(fileno(in),&statbuf) != 0) {
			/* shouldn't happen */
			fprintf(stderr,"%s: can't fstat\n",*argv);
			exit(1);
		    }
		    if((statbuf.st_mode & S_IFMT) == S_IFDIR) {
			fprintf(stderr,"%s is a directory!\n",*argv);
			status++;
		    } else {
			status += process(in,*argv);
		    }
#else
		    status += process(in,*argv);
#endif
		    (void)fclose(in);
		} else {
		    perror(*argv);
		}
	    }
	}
    }
    exit(status);
}


/* process - process input file */
int process(fp,name)
    FILE *fp;
    char *name;
{
    char buf[100],*p,*trip;
    static char trigraph[] =  "=(/)\'<!>-"; /* the lining up is suboptimal.. */
    static char untrichar[] = "#[\\]^{|}~";
    extern char *fgets(),*strchr();
    extern void moveup();

    while(fgets(buf,100,fp)) {
	for(p = buf; p; p = strchr(p+1,'?')) {
	    if(p[1] == '?' && (trip = strchr(trigraph,p[2]))) {
		moveup(p,2);
		*p = untrichar[trip - trigraph];
	    }
	}
	fputs(buf,stdout);
    }

    return(0);
}


/*
 * Using strcpy for moveup() is unportable due to the overlapping areas
 * problem, but basically it is a strcpy(s,s+count).
 */
void moveup(s,count)
    char *s;
    int count;
{
    s += count;
    while(*s) {
	s[-count] = s[0];
	s++;
    }
    s[-count] = '\0';
}
SHAR_EOF
if test 2278 -ne "`wc -c < 'untri.c'`"
then
	echo shar: error transmitting "'untri.c'" '(should have been 2278 characters)'
fi
fi # end of overwriting check
if test -f 'warnt.c'
then
	echo shar: will not over-write existing file "'warnt.c'"
else
cat << \SHAR_EOF > 'warnt.c'
/*
 * warnt.c - print warnings about trigraphs.
 *
 * If you have index() instead of strchr(), compile with -Dstrchr=index.
 *
 * The #ifdef unix lines just provide better arg checking.
 *
 * Alan J Rosenthal <flaps@gpu.utcs.toronto.edu>, 2 June 1988.
 */

#include <stdio.h>
#ifdef unix
#include <sys/types.h>
#include <sys/stat.h>
#endif
#define TRUE	1
#define FALSE	0
#define SUCCESS	0
#define FAILURE	(-1)
#define STREQ(s,t)(*(s) == *(t) && strcmp((s),(t)) == 0)

char *progname;


main(argc,argv)
    int argc;
    char **argv;
{
    int status;
    FILE *in,*fopen();
#ifdef unix
    struct stat statbuf;
#endif

    progname = argv[0];

    status = 0;
    if(argc < 1) /* only some systems */ {
	fprintf(stderr,"usage: %s [file ...]\n",progname);
	exit(1);
    } else if(argc == 1) {
	status += process(stdin,"stdin");
    } else {
	while(--argc > 0) {
	    argv++;
	    if(STREQ(*argv,"-")) {
		status += process(stdin,"-");
	    } else {
		if((in = fopen(*argv,"r"))) {
#ifdef unix
		    if(fstat(fileno(in),&statbuf) != 0) {
			/* shouldn't happen */
			fprintf(stderr,"%s: can't fstat\n",*argv);
			exit(1);
		    }
		    if((statbuf.st_mode & S_IFMT) == S_IFDIR) {
			fprintf(stderr,"%s is a directory!\n",*argv);
			status++;
		    } else {
			status += process(in,*argv);
		    }
#else
		    status += process(in,*argv);
#endif
		    (void)fclose(in);
		} else {
		    perror(*argv);
		}
	    }
	}
    }
    exit(status);
}


/* process - process input file */
int process(fp,name)
    FILE *fp;
    char *name;
{
    int line;
    char buf[100],*p;
    extern char *fgets(),*strchr();

    for(line = 1; fgets(buf,100,fp); line++) {
	for(p = buf; p; p = strchr(p+1,'?'))
	    if(p[1] == '?' && strchr("=(/)\'<!>-",p[2]))
		printf("%s(%d) ??%c: %s",name,line,p[2],buf);
    }

    return(0);
}
SHAR_EOF
if test 1809 -ne "`wc -c < 'warnt.c'`"
then
	echo shar: error transmitting "'warnt.c'" '(should have been 1809 characters)'
fi
fi # end of overwriting check
#	End of shell archive
exit 0