[alt.sources] PL/M to C converter Part 02/03

bob@reed.UUCP (Bob Ankeney) (04/10/91)

#!/bin/sh
# this is part 2 of a multipart archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file io.c continued
#
CurArch=2
if test ! -r s2_seq_.tmp
then echo "Please unpack part 1 first!"
     exit 1; fi
( read Scheck
  if test "$Scheck" != $CurArch
  then echo "Please unpack part $Scheck next!"
       exit 1;
  else exit 0; fi
) < s2_seq_.tmp || exit 1
sed 's/^X//' << 'SHAR_EOF' >> io.c
X}
X
X/*
X *	Print all white space up first new-line (if any).
X *	Move white_space_start to point past first new-line.
X */
Xout_pre_line(token)
XTOKEN	*token;
X{
X	while ((token->white_space_start < token->white_space_end) &&
X		(*token->white_space_start != '\n')) {
X		out_char(*token->white_space_start);
X		token->white_space_start++;
X	}
X}
X
X/*
X *	Print all white space up to but not including last new-line.
X *	Move white_space_start to point to last new-line.
X */
Xout_pre_white(token)
XTOKEN	*token;
X{
X	char	*ptr;
X	int	length;
X
X	for (ptr = token->white_space_end;
X		(ptr > token->white_space_start) && (*(ptr - 1) != '\n') ; )
X			ptr--;
X
X	if (ptr == token->white_space_start)
X		return;
X
X		/* Compute length of white space */
X	length = ptr - token->white_space_start - 1;
X
X	if (length)
X		out_data(token->white_space_start, length);
X
X	token->white_space_start = ptr - 1;
X}
X
X/*
X *	Output token name
X */
Xout_token_name(token)
XTOKEN	*token;
X{
X	if (is_a_type(token))
X		out_type(token->token_type);
X	else
X		out_data(token->token_name, strlen(token->token_name));
X}
X
X/*
X *	Output white space and token name
X */
Xout_token(token)
XTOKEN	*token;
X{
X	out_white_space(token);
X	out_token_name(token);
X}
X
X/*
X *	Output guaranteed white space and token name
X */
Xout_must_token(token)
XTOKEN	*token;
X{
X	out_must_white(token);
X	out_token_name(token);
X}
X
X/*
X *	Output case converted token name
X */
Xout_cvt_name(token)
XTOKEN	*token;
X{
X	char	*ptr;
X
X	for (ptr = token->token_name; *ptr; ptr++) {
X		if (is_a_lc_char(*ptr))
X			out_char(*ptr - 32);
X		else
X		if (is_a_uc_char(*ptr))
X			out_char(*ptr + 32);
X		else
X			out_char(*ptr);
X	}
X}
X
X/*
X *	Output string
X */
Xout_str(string)
Xchar	*string;
X{
X	out_data(string, strlen(string));
X}
X
X/*
X *	Output character
X */
Xout_char(ch)
Xchar	ch;
X{
X	out_data(&ch, 1);
X}
X
X/*
X *	Output new-line if not at start of line
X */
Xout_to_start()
X{
X	if (last_out_ch != LF)
X		out_char(LF);
X}
X
X/*
X *	Output type
X */
Xout_type(type)
Xint	type;
X{
X	switch (type) {
X
X	case BYTE :
X#ifdef CONVERT_TYPES
X		out_str(TYPE_BYTE);
X#else
X		out_str("BYTE");
X#endif
X		break;
X
X	case WORD :
X#ifdef CONVERT_TYPES
X		out_str(TYPE_WORD);
X#else
X		out_str("WORD");
X#endif
X		break;
X
X	case DWORD :
X#ifdef CONVERT_TYPES
X		out_str(TYPE_DWORD);
X#else
X		out_str("DWORD");
X#endif
X		break;
X
X	case INTEGER :
X#ifdef CONVERT_TYPES
X		out_str(TYPE_INTEGER);
X#else
X		out_str("INTEGER");
X#endif
X		break;
X
X	case REAL :
X#ifdef CONVERT_TYPES
X		out_str(TYPE_REAL);
X#else
X		out_str("REAL");
X#endif
X		break;
X
X	case POINTER :
X		out_str(TYPE_POINTER);
X		break;
X
X	default :
X		parse_error("Unknown type");
X	}
X}
X
X/*
X *	Initialize variables for I/O.
X */
Xout_init()
X{
X	out_string = NULL;
X	last_out_ch = '\0';
X	parsing_literal = FALSE;
X}
X
X/*
X *	Output string constant of form 'WXYZ' in form:
X *		'W' << 24 | 'X' << 16 | 'Y' << 8 | Z
X *	where len specifies the number of bytes in the string to output.
X */
Xout_str_const(str_ptr, len)
Xchar	*str_ptr;
Xint	len;
X{
X	while (len-- && *str_ptr) {
X		out_char('\'');
X		if (*str_ptr == '\'')
X			out_char('\\');
X		out_char(*str_ptr++);
X		out_char('\'');
X
X		if (len) {
X			out_str(" << ");
X			out_str(str_shifts[len]);
X			if (*str_ptr)
X				out_str(" | ");
X		}
X	}
X}
X
X/*
X *	Convert NUMERIC constant to octal constant
X */
Xcvt_octal(token, octal_string)
XTOKEN	*token;
Xchar	octal_string[];
X{
X	int	octal;
X	char	ch, *ptr;
X
X	octal = 0;
X	octal_string[0] = '\\';
X	octal_string[4] = '\0';
X
X	ch = *(token->token_start + token->token_length - 1);
X
X		/* Determine base of numeric */
X	if (ch == 'H') {
X			/* Hex */
X		for (ptr = token->token_name + 2; *ptr; ptr++) {
X			octal *= 16;
X			if ((*ptr >= '0') && (*ptr <= '9'))
X				octal += *ptr - '0';
X			else
X			if ((*ptr >= 'A') && (*ptr <= 'Z'))
X				octal += *ptr - 'A' + 10;
X			else
X			if ((*ptr >= 'a') && (*ptr <= 'z'))
X				octal += *ptr - 'a' + 10;
X			else {
X				parse_error("Illegal hex character");
X				return;
X			}
X		}
X	} else
X
X	if ((ch == 'O') || (ch == 'Q')) {
X			/* Octal constant */
X		for (ptr = token->token_name + 1; *ptr; ptr++) {
X			octal *= 8;
X			if ((*ptr >= '0') && (*ptr <= '7'))
X				octal += *ptr - '0';
X			else {
X				parse_error("Illegal decimal character");
X				return;
X			}
X		}
X	} else {
X
X			/* Decimal constant */
X		for (ptr = token->token_name + 1; *ptr; ptr++) {
X			octal *= 10;
X			if ((*ptr >= '0') && (*ptr <= '9'))
X				octal += *ptr - '0';
X			else {
X				parse_error("Illegal decimal character");
X				return;
X			}
X		}
X	}
X
X
X		/* Generate octal constant */
X	octal_string[1] = ((octal >> 6) & 3) + '0';
X	octal_string[2] = ((octal >> 3) & 7) + '0';
X	octal_string[3] = (octal & 7) + '0';
X}
SHAR_EOF
chmod 0660 io.c || echo "restore of io.c fails"
sed 's/^X//' << 'SHAR_EOF' > lit.c &&
X       /*********************************************************************
X        *********************************************************************
X        **                                                                 **
X        **                                                                 **
X        **                            LITERALS                             **
X        **                                                                 **
X        **                                                                 **
X        **  Revision History:  SCO #23  (12/11/84)                         **
X        **                     SCO #31  (02/12/86)       {SCO31.DOC}       **
X        **                     SCO #33  (06/03/86)       {SCO33.DOC}       **
X        **                     SCO #34  (10/28/86)       {SCO34.DOC}       **
X        **                     SCO #36  (07/16/86)       {SCO36.DOC}       **
X        **                     SCO #48  (03/21/87)       {SCO48.DOC}       **
X        **                                                                 **
X        *********************************************************************
X        *********************************************************************/
X
X
X
X
X
X#define POWER_FAIL_SENSE_LATCH 0x0080
X#define INTERRUPT_CONTROLLER_PORT_1 0x00C0
X#define INTERRUPT_CONTROLLER_PORT_2 0x00C2
X#define INSTRUCTION_WORD_1 0x13
X#define INSTRUCTION_WORD_2 0x20
X#define INSTRUCTION_WORD_3 0x01
X#define END_OF_PARITY_INTERRUPT 0x60
X#define END_OF_EXCEPTION_INTERRUPT 0x61
X#define END_OF_REFRESH_INTERRUPT 0x62
X#define END_OF_CYCLE_INTERRUPT 0x63
X#define END_OF_SHORT_INTERRUPT 0x67
X#define INTERRUPT_CONTROLLER_MASK_0 0x0F0
X#define INTERRUPT_CONTROLLER_MASK_1 0x0FC
X#define INTERRUPT_CONTROLLER_MASK_2 0x0F8
X#define INTERRUPT_CONTROLLER_MASK_3 0x0F4
X#define INTERVAL_TIMER_PORT_1 0x0D2
X#define INTERVAL_TIMER_PORT_2 0x0D6
X#define CONTROL_WORD 0x74
X#define DATA_WORD_1 0x12
X#define DATA_WORD_2 0x7A
X#define CONTROL_WORD_87 0x033C
X#define DPM_CONTROL_WORD_87 0x0F3C
X#define BIT_CONTROL_WORD_87 0x0F3C
X#define INTERFACE_1_START_CODE 0x01
X#define INTERFACE_2_START_CODE 0x01
X#define HCP_NORMAL 0x00
X#define HCP_TEST_MODE 0x01
X#define HCP_ADVANCE 0x02
X#define HCP_RESET 0x03
X#define HCP_ALTITUDE_HOLD_RESET 0x04
X#define HCP_FAIL 0x07
X      
X#define IS =
X#define VALID 0x55
X#define NO_COMPUTED_DATA 0x66
X#define FUNCTIONAL_TEST 0x99
X#define TEST_MODE 0x0AA     /*{SCO36.DOC}*/
X#define FLIGHT_MODE 0x55      /*{SCO36.DOC}*/
X#define POSITIVE_BIAS 0        /*{SCO31.DOC}*/
X#define NEGATIVE_BIAS 1        /*{SCO31.DOC}*/
X#define RESET 0x0AA
X#define PASS 0x55
X#define ON 0x55
X#define TO_VOR 0x55
X#define FROM_VOR 0x99
X#define ILS 0x55   /*{SCO48.DOC}*/
X#define VOR 0x0AA   /*{SCO48.DOC}*/
X#define INVALID 0x0AA
X#define OFF 0x0AA
X#define PUSHED 0x55
X#define SET 0x55
X#define FAIL 0x0AA
X#define FAILED 0x0FF
X#define VMC 4
X#define IMC 5
X#define CRZ 6
X#define TOGA 7
X#define BLANK 10
X#define NEGATIVE_SIGN 11
X            
X#define ERROR_DISPLAY 0x5554
X#define PFM_KEY_COUNTER 0x5555
X#define PFM_TIMER 0x5556
X#define COMPUTER_FAULT 0x5557
X#define KEY1 5
X#define KEY2 4
X#define KEY3 3
X#define KEY4 2
X#define KEY5 1
X#define KEY6 0
X#define DISPLAY_GENERATOR_PORT 0x0C000
X#define DISPLAY_GENERATOR_HALT_CODE 3
X#define DISPLAY_GENERATOR_START_CODE 4
X#define DISPLAY_HALT_ENABLE_CODE 0
X#define DG_HALT 0x0005
X#define LOAD_ROTATION_ANGLE 0x0007
X#define LOAD_PRESENT_POSITION 0x0008
X#define DRAW_VECTOR 0x0009
X#define LOAD_BORDERS 0x000D
X#define ZERO_DEGREE_ANGLE 0
X#define NINETY_DEGREE_ANGLE 0x4000
X#define NEG_NINETY_DEGREE_ANGLE 0x0C000
X#define ONE_EIGHTY_DEGREE_ANGLE 0x8000
X#define FIRST_HALF_OF_BUFFER 0
X#define SECOND_HALF_OF_BUFFER 750
X#define WINDOW_COMPARATOR_FAIL 0
X#define WINDOW_COMPARATOR_PASS 7
X#define TWENTY_CYCLES 20
X#define FORTY_CYCLES 40
X      
X#define IOS1_CODE_CHECKSUM_ERROR 0x11     /*{SCO31.DOC}*/
X#define IOS1_RAM_ERROR 0x12     /*{SCO31.DOC}*/
X#define IOS1_80186_ERROR 0x13     /*{SCO31.DOC}*/
X#define IOS1_8087_ERROR 0x14     /*{SCO31.DOC}*/
X#define IOS1_CONVERTOR_ERROR 0x15     /*{SCO31.DOC}*/
X#define IOS1_HUD_POWER_SUPPLY_ERROR 0x16     /*{SCO31.DOC}*/
X#define IOS2_CODE_CHECKSUM_ERROR 0x21     /*{SCO31.DOC}*/
X#define IOS2_RAM_ERROR 0x22     /*{SCO31.DOC}*/
X#define IOS2_80186_ERROR 0x23     /*{SCO31.DOC}*/
X#define IOS2_8087_ERROR 0x24     /*{SCO31.DOC}*/
X#define IOS2_CONVERTOR_ERROR 0x25     /*{SCO31.DOC}*/
X#define CLP_CODE_CHECKSUM_ERROR 0x31     /*{SCO31.DOC}*/
X#define CLP_RAM_ERROR 0x32     /*{SCO31.DOC}*/
X#define CLP_8086_ERROR 0x33     /*{SCO31.DOC}*/
X#define CLP_8087_ERROR 0x34     /*{SCO31.DOC}*/
X#define SM_CODE_CHECKSUM_ERROR 0x41     /*{SCO31.DOC}*/
X#define SM_RAM_ERROR 0x42     /*{SCO31.DOC}*/
X#define SM_8086_ERROR 0x43     /*{SCO31.DOC}*/
X#define SM_8087_ERROR 0x44     /*{SCO31.DOC}*/
X#define SYSTEM_MONITOR_INACTIVE 0x45     /*{SCO31.DOC}*/
X#define DISPLAY_GENERATOR_ERROR 0x51     /*{SCO31.DOC}*/
X#define SYMBOL_MISPOSITIONED_1 0x52     /*{SCO31.DOC}*/
X#define OHU_VIDEO_FAIL 0x63     /*{SCO31.DOC}*/
X#define OHU_HVPS_FAIL 0x64     /*{SCO31.DOC}*/
X#define OHU_95_OR_30_VOLT_SUPPLY_FAIL 0x65     /*{SCO31.DOC}*/
X#define SYMBOL_MISPOSITIONED_2 0x71     /*{SCO31.DOC}*/
X#define WINDOW_COMPARATOR_ERROR 0x77     /*{SCO31.DOC}*/
X#define DEU_VERTICAL_DEFLECTION_FAIL 0x7A     /*{SCO31.DOC}*/
X#define DEU_HORIZONTAL_DEFLECTION_FAIL 0x7B     /*{SCO31.DOC}*/
X#define DEU_DC_SUPPLY_FAIL 0x7C     /*{SCO31.DOC}*/
X#define DEU_BOOST_SUPPLY_FAIL 0x7D     /*{SCO31.DOC}*/
X#define DEU_DEFLECTION_SUPPLY_FAIL 0x7E     /*{SCO31.DOC}*/
X#define TEST_ERROR_DISPLAY 0x88
X#define DISPLAY_GENERATOR_TEST 0x89
X#define HCP_FAILURE 0x91      /*{SCO31.DOC}*/
X#define RSU_FAILURE 0x0A1     /*{SCO34.DOC}*/
X#define COMBINER_NOT_LOCKED 0x0B1     /*{SCO33.DOC}*/
X#define EIGHTH_SECOND 3
X#define ONE_SIXTH_SECOND 3
X#define QUARTER_SECOND 5
X#define ONE_THIRD_SECOND 6
X#define HALF_SECOND 10
X#define ONE_SECOND 20
X#define ONE_POINT_FIVE_SECONDS 30
X#define TWO_SECONDS 40
X#define FIVE_SECONDS 100
X                  
X#define HALF_PI 1.57079633F
X#define PI 3.14159265F
X#define TWO_PI 6.28318531F
X#define TEN_KNOTS 16.9F
X#define TEN_DEGREES 0.1745F
X#define FIFTEEN_DEGREES 0.2618F
X#define MAXIMUM_NUMBER 99999.9F
X                  
X#define FOREVER while (1)
X
SHAR_EOF
chmod 0660 lit.c || echo "restore of lit.c fails"
sed 's/^X//' << 'SHAR_EOF' > main.c &&
X#include <stdio.h>
X#ifdef IBMPC
X#include <stdlib.h>
X#include <sys\stat.h>
X#else
X#include <sys/types.h>
X#include <sys/stat.h>
X#endif
X#include <fcntl.h>
X#include "misc.h"
X#include "defs.h"
X#include "cvt.h"
X#include "struct.h"
X#include "tokens.h"
X#include "tkn_defs.h"
X
Xchar	*text_buffer, *text_ptr;
Xint	line_count;
Xchar	*line_ptr;
Xchar	current_file_name[128];
Xchar	out_file_name[128];
Xint	at_decl_count;
Xchar	at_decl_list[MAX_AT_DECLS][MAX_TOKEN_LENGTH];
XFILE	*ofd;
X
Xint	file_depth;
X
XFILE	*fopen();
X
X/*
X *	Get list of AT declaration variables for EXTERNAL declaration checks
X */
Xget_at_decl()
X{
X	int	i, fd;
X	char	ch;
X
X	at_decl_count = 0;
X	if ((fd = open("at_decl.cvt", O_RDONLY)) == -1)
X			/* Not found */
X		return;
X
X	while (read(fd, &ch, 1) == 1) {
X	    i = 0;
X	    if (!is_a_char(ch)) {
X		fprintf(stderr, "Illegal identifier in line %d at_decl.cvt\n",
X			at_decl_count + 1);
X		exit(1);
X	    }
X	    do {
X#ifdef CONVERT_CASE
X		if (is_a_uc_char(ch))
X				/* Convert to lower case */
X			ch += 32;
X		else
X		if (is_a_lc_char(ch))
X				/* Convert to upper case */
X			ch -= 32;
X#endif
X		at_decl_list[at_decl_count][i++] = ch;
X		if (read(fd, &ch, 1) != 1) {
X			fprintf(stderr, "Unexpected EOF in at_decl.cvt\n");
X			exit(1);
X		}
X	    } while ((ch != '\n') && (ch != ' '));
X
X	    at_decl_list[at_decl_count++][i] = '\0';
X	}
X}
X
X/*
X *	Open specified file, init options, and parse.
X */
Xcvt_file(file_name)
Xchar	*file_name;
X{
X	int		fd, nr;
X	struct	stat	file_stat;
X	TOKEN		token, fname_token, token_module, token_do;
X	int		token_class;
X	char		*tmp_text_buffer, *tmp_text_ptr, *tmp_line_ptr;
X	char		*tmp_ptr;
X	int		tmp_line_count;
X	char		tmp_file_name[128];
X
X	char		*get_mem();
X
X		/* Is this the first file? */
X	if (file_depth) {
X			/* No - save old text pointers */
X		tmp_text_buffer = text_buffer;
X		tmp_text_ptr = text_ptr;
X		tmp_line_ptr = line_ptr;
X		tmp_line_count = line_count;
X		(void) strcpy(tmp_file_name, current_file_name);
X	}
X
X		/* Save file name */
X	(void) strcpy(current_file_name, file_name);
X
X		/* Open file */
X	if ((fd = open(file_name, O_RDONLY)) == -1) {
X		(void) fprintf(stderr, "Cannot open input file %s", file_name);
X		perror("");
X		exit(1);
X	}
X
X		/* Get length */
X	if (fstat(fd, &file_stat)) {
X		perror("Cannot stat input file");
X		exit(1);
X	}
X
X		/* Allocate that much RAM */
X	text_buffer = get_mem((unsigned int) file_stat.st_size + 1);
X
X		/* Read file */
X	if ((nr = read(fd, text_buffer, (int) file_stat.st_size)) == -1) {
X		perror("Cannot read input file");
X		exit(1);
X	}
X
X		/* Insert End-of-file Mark */
X	text_buffer[nr] = '\0';
X	(void) close(fd);
X
X		/* Init pointers */
X	text_ptr = text_buffer;
X	line_ptr = text_ptr;
X	line_count = 1;
X
X		/* Init I/O */
X	out_init();
X
X		/* Start with initial context using file name */
X	(void) strcpy(fname_token.token_name, file_name);
X	fname_token.token_class = IDENTIFIER;
X	new_context(MODULE, &fname_token);
X
X		/* Is this the first file? */
X	if (file_depth++ == 0) {
X			/* Yes - open output file */
X		if ((ofd = fopen(out_file_name, "w")) == NULL) {
X			(void) fprintf(stderr, "Cannot create output file %s",
X				out_file_name);
X			exit(1);
X		}
X
X			/* Check for module name */
X		token_class = get_token(&token_module);
X		out_pre_white(&token_module);
X		tmp_ptr = token_module.token_start;
X		if ((token_class == IDENTIFIER) &&
X				/* Maybe got module name - Check for : */
X		    (get_token(&token) == LABEL) &&
X				/* Check for DO; */
X		   ((get_token(&token_do) == RESERVED) &&
X					(token_do.token_type == DO)) &&
X		    (get_token(&token) == END_OF_LINE)) {
X
X				/* Got module header */
X			out_pre_white(&token_do);
X
X				/* Parse to END [<module name>] */
X			parse_till_end(&token);
X			out_white_space(&token);
X
X			token_class = get_token(&token);
X			if (token_class == IDENTIFIER) {
X				out_pre_white(&token);
X				token_class = get_token(&token);
X			}
X
X				/* Should be at end of line */
X			if (token_class != END_OF_LINE) {
X				parse_error("';' expected");
X			}
X
X				/* Should be at end of file */
X			if (get_token(&token) != END_OF_FILE) {
X				parse_error("End of file expected");
X			}
X			out_white_space(&token);
X		} else {
X			out_pre_white(&token_do);
X			parse_warning("Module name expected");
X			text_ptr = tmp_ptr;
X			parse_file();
X		}
X	} else
X		parse_file();
X
X	free(text_buffer);
X
X		/* Was this the first file? */
X	if (--file_depth) {
X			/* No - restore old text pointers */
X		text_buffer = tmp_text_buffer;
X		text_ptr = tmp_text_ptr;
X		line_ptr = tmp_line_ptr;
X		line_count = tmp_line_count;
X		(void) strcpy(current_file_name, tmp_file_name);
X	} else
X		exit(0);
X}
X
X/*
X *	Open file and init options
X */
Xmain(argc, argv)
Xint	argc;
Xchar	*argv[];
X{
X	int	i;
X	char	ch;
X
X	if (argc != 2) {
X		(void) fprintf(stderr, "usage: %s filename\n", argv[0]);
X		exit(1);
X	}
X
X		/* Search for a '.' in filename */
X	for (i = strlen(argv[1]) - 1; i; i--) {
X		ch = argv[1][i];
X		if ((ch == '.') || (ch == '/') || (ch == '\\'))
X			break;
X	}
X
X	if (ch != '.')
X		i = strlen(argv[1]);
X
X		/* Append a '.c' */
X	(void) strncpy(out_file_name, argv[1], i);
X	out_file_name[i] = '\0';
X	(void) strcat(out_file_name, ".c");
X	(void) printf("Output to: %s\n", out_file_name);
X
X		/* Get AT declaration list */
X	get_at_decl();
X
X		/* Init context */
X	init_context();
X
X	file_depth = 0;
X
X		/* Parse main file */
X	cvt_file(argv[1]);
X}
SHAR_EOF
chmod 0660 main.c || echo "restore of main.c fails"
sed 's/^X//' << 'SHAR_EOF' > makefile &&
X# Makefile for Unix
X
XSRCS =	convert.c	\
X	parse.c		\
X	declare.c	\
X	decl_out.c	\
X	control.c	\
X	io.c		\
X	token.c		\
X	context.c	\
X	mem.c		\
X	error.c		\
X	version.c	\
X	main.c
X
XOBJS =	convert.o	\
X	parse.o		\
X	declare.o	\
X	decl_out.o	\
X	control.o	\
X	io.o		\
X	token.o		\
X	context.o	\
X	mem.o		\
X	error.o		\
X	version.o	\
X	main.o
X
XLNKS =	convert parse declare decl_out control io token context mem error version main
X
XTOKEN_HDRS = misc.h defs.h struct.h cvt.h cvt_id.h tokens.h
XHDRS =	$(TOKEN_HDRS) tkn_defs.h tkn_ext.h
X
XOPTS = -c -O
X
Xplm2c:	$(OBJS)
X	$(CC) -o plm2c $(OBJS)
X
Xconvert.o:	convert.c $(TOKEN_HDRS)
X	$(CC) $(OPTS) convert.c
X
Xparse.o:	parse.c $(TOKEN_HDRS) cvt_id.h
X	$(CC) $(OPTS) parse.c
X
Xdeclare.o:	declare.c $(TOKEN_HDRS)
X	$(CC) $(OPTS) declare.c
X
Xcontrol.o:	control.c $(TOKEN_HDRS) tkn_ext.h
X	$(CC) $(OPTS) control.c
X
Xdecl_out.o:	decl_out.c $(TOKEN_HDRS)
X	$(CC) $(OPTS) decl_out.c
X
Xio.o:	io.c $(TOKEN_HDRS) tkn_ext.h
X	$(CC) $(OPTS) io.c
X
Xtoken.o:	token.c $(TOKEN_HDRS) tkn_ext.h
X	$(CC) $(OPTS) token.c
X
Xcontext.o:	context.c $(TOKEN_HDRS)
X	$(CC) $(OPTS) context.c
X
Xmem.o:	mem.c $(TOKEN_HDRS)
X	$(CC) $(OPTS) mem.c
X
Xerror.o:	error.c $(TOKEN_HDRS)
X	$(CC) $(OPTS) error.c
X
Xversion.o:	version.c
X	$(CC) $(OPTS) version.c
X
Xmain.o:	main.c $(TOKEN_HDRS) tkn_defs.h
X	$(CC) $(OPTS) main.c
X
Xbackup:
X	cp $(HDRS) Makefile bak
X	cp $(SRCS) bak
X
Xlint:
X	lint $(SRCS)
X
Xclean:
X	rm -f $(OBJS)
SHAR_EOF
chmod 0660 makefile || echo "restore of makefile fails"
sed 's/^X//' << 'SHAR_EOF' > makefile.ibm &&
X# Makefile for IBM-PC MSDOS
X
XSRCS =	convert.c	\
X	parse.c		\
X	declare.c	\
X	decl_out.c	\
X	control.c	\
X	io.c		\
X	token.c		\
X	context.c	\
X	mem.c		\
X	error.c		\
X	version.c	\
X	main.c
X
XOBJS =	convert.obj	\
X	parse.obj	\
X	declare.obj	\
X	decl_out.obj	\
X	control.obj	\
X	io.obj		\
X	token.obj	\
X	context.obj	\
X	mem.obj		\
X	error.obj	\
X	version.obj	\
X	main.obj
X
XLNKS =	convert parse declare decl_out control io token context mem error version main
X
XTOKEN_HDRS = misc.h defs.h struct.h cvt.h cvt_id.h tokens.h
XHDRS =	$(TOKEN_HDRS) tkn_defs.h tkn_ext.h
X
XMDL =	m
XOPTS = -c -N -v -DIBMPC -m$(MDL)
X
Xplm2c:	$(OBJS)
X	tlink /c /v c:\tc\lib\c0$(MDL) $(LNKS), plm2c, plm2c, c:\tc\lib\c$(MDL)
X
Xconvert.obj:	convert.c $(TOKEN_HDRS)
X	tcc $(OPTS) convert
X
Xparse.obj:	parse.c $(TOKEN_HDRS) cvt_id.h
X	tcc $(OPTS) parse
X
Xdeclare.obj:	declare.c $(TOKEN_HDRS)
X	tcc $(OPTS) declare
X
Xcontrol.obj:	control.c $(TOKEN_HDRS) tkn_ext.h
X	tcc $(OPTS) control
X
Xdecl_out.obj:	decl_out.c $(TOKEN_HDRS)
X	tcc $(OPTS) decl_out
X
Xio.obj:	io.c $(TOKEN_HDRS) tkn_ext.h
X	tcc $(OPTS) io
X
Xtoken.obj:	token.c $(TOKEN_HDRS) tkn_ext.h
X	tcc $(OPTS) token
X
Xcontext.obj:	context.c $(TOKEN_HDRS)
X	tcc $(OPTS) context
X
Xmem.obj:	mem.c $(TOKEN_HDRS)
X	tcc $(OPTS) mem
X
Xerror.obj:	error.c $(TOKEN_HDRS)
X	tcc $(OPTS) error
X
Xversion.obj:	version.c
X	tcc $(OPTS) version
X
Xmain.obj:	main.c $(TOKEN_HDRS) tkn_defs.h
X	tcc $(OPTS) main
X
Xbackup:
X	cp $(HDRS) Makefile bak
X	cp $(SRCS) bak
X
Xfloppy:
X	cp $(HDRS) makefile a:
X	cp $(SRCS) a:
X
Xlint:
X	lint $(SRCS)
X
SHAR_EOF
chmod 0660 makefile.ibm || echo "restore of makefile.ibm fails"
sed 's/^X//' << 'SHAR_EOF' > mem.c &&
X#ifdef IBMPC
X#include <alloc.h>
X#endif
X#include "misc.h"
X#include "defs.h"
X#include "cvt.h"
X#include "struct.h"
X
X/*
X *	Memory allocation and deallocation routines.
X */
X
X/*
X *	Allocate memory
X */
Xchar *get_mem(size)
Xunsigned int	size;
X{
X	char	*malloc_ptr;
X	void	*malloc();
X
X	if ((malloc_ptr = (char *)malloc(size)) == NULL) {
X		parse_error("Out of memory");
X		exit(1);
X	}
X	return malloc_ptr;
X}
X
X/*
X *	Generate a new context.
X */
Xget_context_ptr(context)
XCONTEXT	**context;
X{
X	*context = (CONTEXT *) get_mem(sizeof(CONTEXT));
X	(*context)->decl_head = NULL;
X	(*context)->next_context = NULL;
X}
X
X/*
X *	Malloc memory for a TOKEN.
X */
Xget_token_ptr(token)
XTOKEN	**token;
X{
X	*token = (TOKEN *) get_mem(sizeof(TOKEN));
X}
X
X/*
X *	Malloc memory for a DECL_ID.
X */
Xget_var_ptr(var)
XDECL_ID	**var;
X{
X	*var = (DECL_ID *) get_mem(sizeof(DECL_ID));
X	(*var)->name = NULL;
X	(*var)->based_name = NULL;
X	(*var)->next_var = NULL;
X	(*var)->is_ext_at = FALSE;
X}
X
X/*
X *	Free a linked list of variables.
X */
Xfree_var_list(list_ptr)
XDECL_ID	*list_ptr;
X{
X	DECL_ID	*next_ptr;
X
X	while (list_ptr) {
X		if (list_ptr->name)
X			free( (char *) list_ptr->name);
X		if (list_ptr->based_name)
X			free( (char *) list_ptr->based_name);
X		next_ptr = list_ptr->next_var;
X		free((char *) list_ptr);
X		list_ptr = next_ptr;
X	}
X}
X
X/*
X *	Malloc space for a DECL_MEMBER structure and return pointer.
X */
Xget_element_ptr(element)
XDECL_MEMBER	**element;
X{
X	DECL_MEMBER	*el_ptr;
X
X		/* Malloc space for element */
X	el_ptr = (DECL_MEMBER *) get_mem(sizeof(DECL_MEMBER));
X
X		/* Init pointers */
X	el_ptr->name_list = NULL;
X	el_ptr->literal = NULL;
X#ifdef PARSE_LITERALS
X	el_ptr->literal_token = NULL;
X#endif
X	el_ptr->array_bound = NULL;
X	el_ptr->type = NULL;
X	el_ptr->struct_list = NULL;
X	el_ptr->at_ptr = NULL;
X	el_ptr->init_ptr = NULL;
X	el_ptr->next_member = NULL;
X
X	el_ptr->attributes = NONE;
X	el_ptr->initialization = NONE;
X
X	*element = el_ptr;
X}
X
X/*
X *	Free a DECL_MEMBER list.
X */
Xfree_decl_list(element)
XDECL_MEMBER	*element;
X{
X	DECL_MEMBER	*el_ptr;
X
X	while (element) {
X		if (element->name_list)
X			free_var_list(element->name_list);
X		if (element->literal)
X			free((char *) element->literal);
X		if (element->array_bound)
X			free((char *) element->array_bound);
X		if (element->type)
X			free((char *) element->type);
X		if (element->struct_list)
X			free_decl_list(element->struct_list);
X		if (element->at_ptr)
X			free(element->at_ptr);
X
X		el_ptr = element->next_member;
X		free((char *) element);
X		element = el_ptr;
X	}
X}
X
X/*
X *	Malloc space for a procedure parameter
X */
Xget_param_ptr(param)
XPARAM_LIST	**param;
X{
X	*param = (PARAM_LIST *) get_mem(sizeof(PARAM_LIST));
X	(*param)->next_param = NULL;
X}
X
X/*
X *	Free parameter list
X */
Xfree_param_list(param_list)
XPARAM_LIST	*param_list;
X{
X	PARAM_LIST	*param_ptr;
X
X	while (param_list) {
X		param_ptr = param_list->next_param;
X		free((char *) param_list);
X		param_list = param_ptr;
X	}
X}
X
X/*
X *	Malloc space for a DECLARE statement
X */
Xget_decl_ptr(decl)
XDECL	**decl;
X{
X	*decl = (DECL *) get_mem(sizeof(DECL));
X	(*decl)->decl_list = NULL;
X	(*decl)->next_decl = NULL;
X}
X
X/*
X *	Free DECL list
X */
Xfree_decl(decl_list)
XDECL	*decl_list;
X{
X	DECL	*decl_ptr;
X
X	while (decl_list) {
X		decl_ptr = decl_list->next_decl;
X#ifdef FREE_DECL_TOKEN
X		if (decl_list->decl_token)
X			free((char *) decl_list->decl_token);
X#endif
X		if (decl_list->decl_list)
X			free_decl_list(decl_list->decl_list);
X		free((char *) decl_list);
X		decl_list = decl_ptr;
X	}
X}
X
X
SHAR_EOF
chmod 0660 mem.c || echo "restore of mem.c fails"
sed 's/^X//' << 'SHAR_EOF' > misc.h &&
X/*
X *	Miscellaneous defines
X */
Xtypedef	unsigned char	BYTE;
Xtypedef	unsigned char	BOOLEAN;
X
X
X#ifndef TRUE
X#define TRUE	1
X#endif
X
X#ifndef FALSE
X#define FALSE	0
X#endif
X
X#ifndef NULL
X#define NULL	0
X#endif
X
X/*
X *	White space characters
X */
X#define	SPACE	' '
X#define TAB	9
X#define CR	13
X#define LF	10
X
X/*
X *	Useful defines
X */
X#define is_a_uc_char(char) ((char >= 'A') && (char <= 'Z'))
X#define is_a_lc_char(char) ((char >= 'a') && (char <= 'z'))
X#define is_a_char(char) (((char & 0x5F) >= 'A') && ((char & 0x5F) <= 'Z'))
X#define is_a_digit(char) ((char >= '0') && (char <= '9'))
X
X#define is_a_type(token) ((token->token_class == RESERVED) && \
X		(token->token_type >= BYTE) && (token->token_type <= REAL))
X
X#define is_white(ch) ((ch == ' ') || (ch == TAB))
X
X#define NONE	0
X
Xchar	*strcat(), *strncat(), *strcpy(), *strncpy();
X#ifdef IBMPC
Xint	sprintf();
X#endif
SHAR_EOF
chmod 0660 misc.h || echo "restore of misc.h fails"
sed 's/^X//' << 'SHAR_EOF' > parse.c &&
X#include <stdio.h>
X#ifdef IBMPC
X#include <stdlib.h>
X#endif
X#include "misc.h"
X#include "defs.h"
X#include "cvt.h"
X#include "struct.h"
X#include "cvt_id.h"
X#include "tokens.h"
X
Xextern	char	*text_buffer, *text_ptr;
Xextern	int	line_count;
Xextern	char	*out_string;
X
X/*
X *	Parse a procedure parameter list.
X *	Return head of linked list of parameters.
X */
Xget_param_list(param_head)
XPARAM_LIST	**param_head;
X{
X	PARAM_LIST	*list_ptr, *param_ptr;
X	int		token_class;
X	TOKEN		sep_token;
X
X	*param_head = NULL;
X	list_ptr = NULL;
X
X	do {
X		get_param_ptr(&param_ptr);
X		if (*param_head == NULL)
X			*param_head = param_ptr;
X		if (list_ptr)
X			list_ptr->next_param = param_ptr;
X		list_ptr = param_ptr;
X		token_class = get_token(&param_ptr->param);
X		if (token_class != IDENTIFIER) {
X			parse_error("Identifier expected");
X			free_param_list(*param_head);
X		}
X			/* Get ',' or ')' */
X		token_class = get_token(&sep_token);
X	} while (token_class == COMMA);
X
X	if (token_class != RIGHT_PAREN) {
X		parse_error("')' expected");
X		free_param_list(*param_head);
X	}
X}
X
X/*
X *	Parse parameter list.
X *	Parse DECLARE statements until all parameters in param_list
X *	have been found.  Split declare statements into those used in
X *	param_list and those not.  Return pointers to head of both
X *	DECL_MEMBER lists.
X */
Xparse_param_list(param_list, decl_list, extra_decl_list)
XPARAM_LIST	*param_list;
XDECL		**decl_list, **extra_decl_list;
X{
X	DECL		*extra_decl, *extra_decl_ptr;
X	DECL		*list, *list_ptr;
X	DECL_MEMBER	*extra_list_ptr;
X	DECL_MEMBER	*el_ptr, *last_el_ptr, *next_el_ptr;
X	DECL_MEMBER	*extra_el_ptr;
X	int		token_class;
X	TOKEN		*decl_token;
X	DECL_ID		*var_ptr, *last_var_ptr, *next_var_ptr;
X	DECL_ID		*extra_last_var_ptr;
X	PARAM_LIST	*param_ptr, *last_param;
X
X	*decl_list = NULL;
X	*extra_decl_list = NULL;
X		/* Pointer to next DECL_MEMBER in decl_ptr */
X	list_ptr = NULL;
X		/* Pointer to next DECL in extra_decl_list */
X	extra_decl_ptr = NULL;
X
X	while (param_list) {
X		    /* Get declaration */
X	    get_token_ptr(&decl_token);
X	    token_class = get_token(decl_token);
X	    if ((token_class != RESERVED) ||
X			(decl_token->token_type != DECLARE)) {
X			parse_error("DECLARE expected");
X			free((char *) decl_token);
X			return;
X	    }
X		    /* Get declaration list */
X	    get_decl_ptr(&list);
X	    get_decl_list(list);
X	    list->decl_token = decl_token;
X
X		    /* Points to start of extra declaration list */
X	    extra_list_ptr = NULL;
X
X		    /* Pointer to previous el_ptr */
X	    last_el_ptr = NULL;
X
X		    /* Check each element of the DECLARE statement */
X	    el_ptr = list->decl_list;
X	    while (el_ptr) {
X
X			/* Point to next member */
X		next_el_ptr = el_ptr->next_member;
X
X			/* Pointer to next DECL_MEMBER in extra_decl_ptr */
X		extra_el_ptr = NULL;
X
X			/* Points to last variable in variable list */
X		last_var_ptr = NULL;
X			/* Contains not found variables in name_list */
X		extra_last_var_ptr = NULL;
X
X			/* Check each variable in name list */
X		for (var_ptr = el_ptr->name_list; var_ptr; ) {
X			/* Point to following var_ptr */
X		    next_var_ptr = var_ptr->next_var;
X
X				/* Is this variable in param list? */
X		    last_param = NULL;
X		    for (param_ptr = param_list; param_ptr;
X				param_ptr = param_ptr->next_param) {
X			if (!strcmp(param_ptr->param.token_name,
X			    var_ptr->name->token_name))
X			    break;
X			else
X			    last_param = param_ptr;
X		    }
X
X		    if (param_ptr) {
X
X				/* Variable found */
X				/* Remove from parameter list */
X			if (last_param)
X			    last_param->next_param = param_ptr->next_param;
X			else
X			    param_list = param_ptr->next_param;
X
X			free((char *) param_ptr);
X		        last_var_ptr = var_ptr;
X		    } else {
X/*
X *	Variable not found - Add to extra variable list
X */
X			if (extra_el_ptr == NULL) {
X/*
X *	Create new element and copy DECLARE info
X */
X			    get_element_ptr(&extra_el_ptr);
X			    element_copy(el_ptr, extra_el_ptr);
X			    extra_last_var_ptr = NULL;
X/*
X *	Link new extra element into extra_list_ptr
X */
X			    if (extra_list_ptr) {
X				extra_list_ptr->next_member = extra_el_ptr;
X			    } else {
X/*
X *	Create new extra declaration
X */
X				get_decl_ptr(&extra_decl);
X
X					/* Point to DECLARE token */
X				extra_decl->decl_token =
X					list->decl_token;
X				extra_decl->decl_list = extra_el_ptr;
X/*
X *	Link new extra declaration into extra_decl_list
X */
X				if (extra_decl_ptr)
X				    extra_decl_ptr->next_decl = extra_decl;
X				else
X				    *extra_decl_list = extra_decl;
X
X				extra_decl_ptr = extra_decl;
X			    }
X			    extra_list_ptr = extra_el_ptr;
X			}
X
X				/* Add var_ptr to extra list */
X			if (extra_last_var_ptr)
X			    extra_last_var_ptr->next_var = var_ptr;
X			else
X			    extra_list_ptr->name_list = var_ptr;
X
X			extra_last_var_ptr = var_ptr;
X
X				/* Remove from DECLARE list */
X			if (last_var_ptr)
X			    last_var_ptr->next_var = next_var_ptr;
X			else
X			    el_ptr->name_list = next_var_ptr;
X
X			var_ptr->next_var = NULL;
X		    }
X
X		    var_ptr = next_var_ptr;
X		}
X
X/*
X *	Check for empty name list
X */
X		if (el_ptr->name_list == NULL) {
X/*
X *	Empty name list - unlink and discard element from declaration list
X */
X		    if (last_el_ptr)
X			last_el_ptr->next_member = next_el_ptr;
X		    else
X			list->decl_list = next_el_ptr;
X
X		    el_ptr->next_member = NULL;
X		    free((char *) el_ptr);
X		} else
X		    last_el_ptr = el_ptr;
X
X		el_ptr = next_el_ptr;
X	    }
X
X		    /* Save found items in decl_list */
X	    if (list->decl_list->name_list) {
X		if (*decl_list)
X		    list_ptr->next_decl = list;
X		else
X		    *decl_list = list;
X		list_ptr = list;
X	    } else
X		free((char *) list);
X
X	}
X}
X
X/*
X *	Parse until desired token type appears
X */
Xparse_till(type, token)
Xint	type;
XTOKEN	*token;
X{
X	while (get_token(token) != type)
X		out_token(token);
X}
X
X/*
X *	Parse until END statement
X */
Xparse_till_end(token)
XTOKEN	*token;
X{
X	int	token_class;
X
X	while (1) {
X		token_class = get_token(token);
X
X		if (token_class == END_OF_FILE) {
X			parse_error("Premature end-of-file");
X			exit(1);
X		}
X
X		if ((token_class == RESERVED) && (token->token_type == END))
X			return;
X
X		parse_statement(token);
X	}
X}
X
X/*
X *	Parse through END statement
X */
Xparse_to_end()
X{
X	TOKEN	token;
X
X	parse_till_end(&token);
X	parse_statement(&token);
X}
X
X/*
X *	Check for end of line (';')
X */
Xcheck_eol()
X{
X	TOKEN	token;
X
X	if (get_token(&token) != END_OF_LINE)
X		parse_error("';' expected");
X	else
X		out_token(&token);
X}
X
X/*
X *	Parse simple variable and return variable token and following token.
X *	Passed with initial identifier in token.
X *	Returns with next_token terminating variable.
X *	Handles [ .<identifier> ] ...
X */
Xparse_simple_variable(token, next_token)
XTOKEN	*token, *next_token;
X{
X	int	token_class;
X
X	while (1) {
X		token_class = get_token(next_token);
X		if (token_class != PERIOD)
X			return token_class;
X
X			/* Process .<identifier> */
X		token_class = get_token(next_token);
X		if (token_class != IDENTIFIER) {
X			parse_error("Illegal identifier");
X			return ERROR;
X		}
X			/* Add .<identifier> to original token name */
X		(void) strcat(token->token_name, ".");
X		(void) strcat(token->token_name, next_token->token_name);
X			/* Parse for additional member */
X		return parse_simple_variable(token, next_token);
X	}
X}
X
X/*
X *	Parse variable identifier.  If pointer, output (*ident) else
X *	If variable has BASED attribute, output (*based_name).
X *	Otherwise, output ident.
X */
Xout_ident(ident, decl, decl_id)
XTOKEN		*ident;
XDECL_MEMBER	*decl;
XDECL_ID		*decl_id;
X{
X	if (decl->at_ptr || decl_id->is_ext_at) {
X		out_white_space(ident);
X		out_str("(*");
X		out_token_name(ident);
X		out_char(')');
X	} else
X
X	if (decl_id->based_name) {
X		out_white_space(ident);
X		out_str("(**");
X		out_token_name(decl_id->name);
X		out_char(')');
X	} else
X		out_token(ident);
X}
X
X/*
X *	Parse variable name or structure element and output appropriate tokens.
X *	Passed with identifier in token, and declaration for token in decl.
X *	Returns with token terminating variable.
X *	Handles <member> { [ ( <expression> ) ] [ .<identifier> ] }
X */
Xparse_member(token, decl, decl_id)
XTOKEN		*token;
XDECL_MEMBER	*decl;
XDECL_ID		*decl_id;
X{
X	int		token_class;
X	TOKEN		member;
X	DECL_MEMBER	*var_decl;
X	DECL_ID		*var_decl_id;
X
X		/* Check for literal */
X	if (decl->literal) {
X			/* Yes - output case converted literal */
X		out_white_space(token);
X		out_cvt_name(token);
X			/* Return next token */
X		token_class = get_token(token);
X		return token_class;
X	}
X
X	token_copy(token, &member);
X
X	token_class = get_token(token);
X
X		/* Check for array subscript */
X	if (decl->array_bound) {
X	    out_ident(&member, decl, decl_id);
X
X	    if (token_class == LEFT_PAREN) {
X			/* Convert to open square bracket */
X		token->token_name[0] = '[';
X		out_token(token);
X
X			/* Parse expression to right parenthesis */
X		token_class = parse_expression(token);
X		if (token_class != RIGHT_PAREN) {
X			parse_error("')' expected");
X			return ERROR;
X		}
X
X			/* Convert to close square bracket */
X		token->token_name[0] = ']';
X		out_token(token);
X
X		token_class = get_token(token);
X	    }
X	}
X
X		/* Check for .<identifier> */
X	if ((decl->type->token_type == STRUCTURE) && (token_class == PERIOD)) {
X
X		if (decl->array_bound)
X				/* Already printed identifier */
X			out_token(token);
X		else {
X			if (decl->at_ptr || decl_id->based_name) {
X/*
X * --- Note: Does not handle BASED AT variables!
X */
X					/* Print 'member->' */
X				out_token(&member);
X				out_str("->");
X			} else {
X					/* Print 'member.' */
X				out_ident(&member, decl, decl_id);
X				out_token(token);
X			}
X		}
X
X		token_class = get_token(token);
X		if (token_class != IDENTIFIER) {
X			parse_error("Illegal structure member");
X			return ERROR;
X		}
X
X			/* Find variable in list */
X		if (!find_list_symbol(token, decl->struct_list,
X					&var_decl, &var_decl_id)) {
X			parse_error("Undefined structure member");
X			return ERROR;
X		}
X
X			/* Parse this member now */
X		token_class = parse_member(token, var_decl, var_decl_id);
X	} else
X	    if (decl->array_bound == NULL)
X		out_ident(&member, decl, decl_id);
X
X	return token_class;
X}
X
X/*
X *	Parse variable and output appropriate tokens.
X *	Passed with initial identifier in token.
X *	Returns with token terminating variable.
X *	Handles { [ ( <expression> ) ] [ .<identifier> ] } ...
X */
Xparse_variable(token, var_decl, var_decl_id)
XTOKEN		*token;
XDECL_MEMBER	**var_decl;
XDECL_ID		**var_decl_id;
X{
X	if (!find_symbol(token, var_decl, var_decl_id)) {
X		parse_error("Undefined variable");
X		return ERROR;
X	}
X
X	return parse_member(token, *var_decl, *var_decl_id);
X}
X
X/*
X *	See if token is in cvt_list.
X *	If found, return pointer to conversion string.
X */
Xcheck_cvt_id(token, cvt_id, cvt_string)
XTOKEN	*token;
XCVT_ID	*cvt_id;
Xchar	**cvt_string;
X{
X		/* Check each string in cvt_id */
X	while (*(cvt_id->id_name)) {
X		if (!strcmp(token->token_name, cvt_id->id_name)) {
X				/* Found match - return new string */
X			*cvt_string = cvt_id->new_id;
X			return TRUE;
X		}
X
X		cvt_id++;
X	}
X
X	return FALSE;
X}
X
X/*
X *	Parse function call
X */
Xparse_function(token)
XTOKEN	*token;
X{
X	int		token_class;
X	BOOLEAN		left_shift, right_shift;
X	char		*new_func;
X	DECL_MEMBER	*decl_ptr;
X	DECL_ID		*decl_id;
X
X		/* Function call - check for SHL or SHR */
X	out_white_space(token);
X	left_shift = !strcmp(token->token_name, "shl") ||
X		     !strcmp(token->token_name, "SHL");
X	right_shift = !strcmp(token->token_name, "shr") ||
X		      !strcmp(token->token_name, "SHR");
X	if (left_shift || right_shift) {
X			/* SHL(expr, expr) or SHR(expr, expr) */
X			/* Check for '(' */
X		token_class = get_token(token);
X		if (token_class != LEFT_PAREN) {
X			parse_error("'(' expected");
X			return ERROR;
X		}
X		out_token(token);
X
X			/* Output first expression */
X		out_char('(');
X		token_class = parse_expression(token);
X		if (token_class != COMMA) {
X			parse_error("',' expected");
X			return ERROR;
X		}
X
X		out_str(left_shift ? ") << (" : ") >> (");
X
X			/* Output second expression */
X		token_class = parse_expression(token);
X		if (token_class != RIGHT_PAREN) {
X			parse_error("Missing ')'");
X			return ERROR;
X		}
X		out_char(')');
X		out_token(token);
X	} else {
X
X			/* Check for a type cast function */
X		if (check_cvt_id(token, &cast_functions[0], &new_func)) {
X				/* Convert to a cast */
X			out_char('(');
X			out_str(new_func);
X			out_str(") ");
X		} else
X
X			/* Check for a function conversion */
X		if (check_cvt_id(token, &cvt_functions[0], &new_func)) {
X				/* Convert to desired function */
X			out_str(new_func);
X		} else {
X
X				/* Output function name */
X			out_token_name(token);
X
X				/* Check for parameter list */
X			if (find_symbol(token, &decl_ptr, &decl_id)) {
X			    if (decl_ptr->type->token_type != PROCEDURE) {
X				parse_error("Illegal function call");
X				return ERROR;
X			    }
X			    if (decl_ptr->initialization != DATA) {
X					/* No param list */
X				token_class = get_token(token);
X				return token_class;
X			    }
X			}
X		}
X
X			/* Check for parameter list */
X		token_class = get_token(token);
X		if (token_class != LEFT_PAREN) {
X			parse_warning("Parameter list expected");
X			return token_class;
X		}
X		out_token(token);
X
X			/* Parse to closing right paren */
X		do {
X			token_class = parse_expression(token);
X			out_token(token);
X		} while (token_class == COMMA);
X
X		if (token_class != RIGHT_PAREN) {
X			parse_error("Missing ')'");
X			return ERROR;
X		}
X	}
X		/* Return token following function */
X	token_class = get_token(token);
X	return token_class;
X}
X
X/*
X *	Parse expression and output appropriate tokens.
X *	Return token at end of expression.
X */
Xparse_expression(token)
XTOKEN	*token;
X{
X    int		token_class;
X    int		i, last_class, temp_class;
X    DECL_MEMBER	*id_type;
X    DECL_ID	*id_id;
X    char	*new_id;
X    char	string_const[MAX_TOKEN_LENGTH], octal_const[5];
X
X    last_class = OPERATOR;
X
X    token_class = get_token(token);
X
X    while (1) {
X
X	switch (token_class) {
X
X	case LEFT_PAREN :
X		if (last_class != OPERATOR) {
X			parse_error("Missing operator");
X			return ERROR;
X		}
X
X			/* Sub-expression */
X		out_token(token);
X			/* Parse to closing right paren */
X		token_class = parse_expression(token);
X		if (token_class != RIGHT_PAREN) {
X			parse_error("Missing ')'");
X			return ERROR;
X		}
X
X		out_token(token);
X		break;
X
X	case RIGHT_PAREN :
X		return token_class;
X
X	case OPERATOR :
X		out_white_space(token);
X		if (token->token_type == EQUAL)
X				/* Make it a '==' */
X			out_str("==");
X		else
X
X			/* Check for address operator '@' or '.' */
X		if ((token->token_type == AT_OP) ||
X				(token->token_type == PERIOD)) {
X		    token_class = get_token(token);
X		    if (token_class == IDENTIFIER) {
X				/* Make it a '&' */
X			out_char('&');
X
X				/* See if it's a function reference */
X			if (find_symbol(token, &id_type, &id_id) &&
X			    (id_type->type->token_type != PROCEDURE)) {
X				    /* Variable - parse it */
X			    temp_class = parse_member(token, id_type, id_id);
X			} else {
X
X				    /* Function call - Check for */
X				    /* a function conversion */
X			    if (check_cvt_id(token, &cvt_functions[0], &new_id))
X					    /* Convert to desired function */
X				    out_str(new_id);
X			    else
X				    	    /* Function call - output name */
X			    	    out_token_name(token);
X
X			    temp_class = get_token(token);
X			}
X		    } else
X
X		    if (token_class == LEFT_PAREN) {
X				/* Constant list - convert to string */
X			out_char('"');
X			string_const[0] = '\0';
X
X			do {
X				token_class = get_token(token);
X				if (token_class == STRING)
X					(void) strcat(string_const, token->token_name);
X				else
X				if (token_class == NUMERIC) {
X					cvt_octal(token, octal_const);
X					(void) strcat(string_const, octal_const);
X				} else {
X					parse_error("Illegal constant");
X					return ERROR;
X				}
X
X				token_class = get_token(token);
X			} while (token_class == COMMA);
X
X			if (token_class != RIGHT_PAREN) {
X				parse_error("')' expected");
X				return ERROR;
X			}
X
X			i = strlen(string_const);
X			if ((i >= 4) &&
X				(!strcmp(string_const + i - 4, "\\000")))
X					/* Discard trailing null */
X				string_const[i - 4] = '\0';
X			out_str(string_const);
X			out_char('"');
X		    } else {
X			parse_error("Illegal operator");
X			return ERROR;
X		    }
X		} else
X
X			out_token_name(token);
X		break;
X
X	case IDENTIFIER :
X			/* Check for identifier conversion */
X		if (check_cvt_id(token, &cvt_identifiers[0], &new_id)) {
X			out_white_space(token);
X			out_str(new_id);
X			temp_class = get_token(token);
X		} else
X
X			/* See if variable in context */
X		if (find_symbol(token, &id_type, &id_id) &&
X			(id_type->type->token_type != PROCEDURE)) {
X				/* Variable - parse it */
X			temp_class = parse_member(token, id_type, id_id);
X		} else
X
X				/* Function call - parse it */
X			temp_class = parse_function(token);
X		break;
X
X	case NUMERIC :
X		out_token(token);
X		break;
X
X	case STRING :
X		out_white_space(token);
X			/* Convert to a numeric constant */
X		if (token->token_length > 4) {
X			parse_error("Illegal string constant");
X			return ERROR;
X		}
X
X		if (token->token_length > 1)
X			out_char('(');
X
X		out_str_const(token->token_name, token->token_length);
X
X		if (token->token_length > 1)
X			out_char(')');
X		break;
X
X	default :
X		/* Must not be part of an expression! */
X		return token_class;
X	}
X
X	last_class = token_class;
X
X	token_class = (last_class == IDENTIFIER) ?
X			temp_class : get_token(token);
X    }
X}
X
X/*
X *	DO statement
X *	Handles DO;, DO CASE, DO WHILE, and iterative DO
X */
Xparse_do(first_token)
XTOKEN	*first_token;
X{
X	TOKEN		token;
X	int		token_class;
X	int		case_line;
X	char		case_statement[MAX_TOKEN_LENGTH];
X	char		case_output[MAX_CASE_STATEMENT_SIZE];
X	char		var_string[MAX_TOKEN_LENGTH];
X	char		*temp_out_string, *temp_out_string1;
X	DECL_MEMBER	*var_decl;
X	DECL_ID		*var_decl_id;
X
X		/* Create new context */
X	new_context(DO, (TOKEN *) NULL);
X
X	out_white_space(first_token);
X
X		/* Determine what kind of DO statement */
X	token_class = get_token(&token);
X
X	switch (token_class) {
X
X	case END_OF_LINE :
X			/* DO; */
X		out_white_space(&token);
X		out_char('{');			/* } for dumb vi */
X		parse_to_end();
X		break;
X
X	case IDENTIFIER :
X			/* DO counter = start TO limit BY step */
X		out_str("for");
X		out_must_white(&token);
X		out_char('(');
X
X			/* Put full variable in var_string */
X		var_string[0] = '\0';
X		temp_out_string = out_string;
X		out_string = var_string;
X		token_class = parse_variable(&token, &var_decl, &var_decl_id);
SHAR_EOF
echo "End of part 2, continue with part 3"
echo "3" > s2_seq_.tmp
exit 0