341 lines
		
	
	
	
		
			5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			341 lines
		
	
	
	
		
			5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /* $Header$ */
 | |
| 
 | |
| /* Language dependant support; this one is default */
 | |
| 
 | |
| #include <stdio.h>
 | |
| #include <alloc.h>
 | |
| 
 | |
| #include "position.h"
 | |
| #include "class.h"
 | |
| #include "langdep.h"
 | |
| #include "Lpars.h"
 | |
| #include "idf.h"
 | |
| #include "token.h"
 | |
| #include "expr.h"
 | |
| #include "tree.h"
 | |
| #include "operator.h"
 | |
| 
 | |
| extern FILE *db_out, *db_in;
 | |
| 
 | |
| extern int
 | |
| 	get_name();
 | |
| 
 | |
| extern double
 | |
| 	atof();
 | |
| 
 | |
| static int
 | |
| 	print_string(),
 | |
| 	get_number(),
 | |
| 	get_string(),
 | |
| 	get_token(),
 | |
| 	print_op(),
 | |
| 	op_prio();
 | |
| 
 | |
| static long
 | |
| 	array_elsize();
 | |
| 
 | |
| static struct langdep def = {
 | |
| 	0,
 | |
| 
 | |
| 	"%ld",
 | |
| 	"0%lo",
 | |
| 	"0x%lX",
 | |
| 	"%lu",
 | |
| 	"0x%lX",
 | |
| 	"%g",
 | |
| 	"'\\%o'",
 | |
| 
 | |
| 	"[",
 | |
| 	"]",
 | |
| 	"(",
 | |
| 	")",
 | |
| 	"{",
 | |
| 	"}",
 | |
| 
 | |
| 	print_string,
 | |
| 	array_elsize,
 | |
| 	op_prio,
 | |
| 	get_string,
 | |
| 	get_name,
 | |
| 	get_number,
 | |
| 	get_token,
 | |
| 	print_op
 | |
| };
 | |
| 
 | |
| struct langdep *def_dep = &def;
 | |
| 
 | |
| static int
 | |
| print_string(s, len)
 | |
|   char	*s;
 | |
|   int	len;
 | |
| {
 | |
|   register char	*str = s;
 | |
|   int delim = '\'';
 | |
| 
 | |
|   while (*str) {
 | |
| 	if (*str++ == '\'') delim = '"';
 | |
|   }
 | |
|   fprintf(db_out, "%c%.*s%c", delim, len, s, delim);
 | |
| }
 | |
| 
 | |
| extern long	int_size;
 | |
| 
 | |
| static long
 | |
| array_elsize(size)
 | |
|   long	size;
 | |
| {
 | |
|   if (! (int_size % size)) return size;
 | |
|   if (! (size % int_size)) return size;
 | |
|   return ((size + int_size - 1) / int_size) * int_size;
 | |
| }
 | |
| 
 | |
| /*ARGSUSED*/
 | |
| static int
 | |
| op_prio(op)
 | |
|   int	op;
 | |
| {
 | |
|   return 1;
 | |
| }
 | |
| 
 | |
| static int
 | |
| val_in_base(c, base)
 | |
|   register int c;
 | |
| {
 | |
|   return is_dig(c) 
 | |
| 	? c - '0'
 | |
| 	: base != 16
 | |
| 	  ? -1
 | |
| 	  : is_hex(c)
 | |
| 	    ? (c - 'a' + 10) & 017
 | |
| 	    : -1;
 | |
| }
 | |
| 
 | |
| static int
 | |
| get_number(c)
 | |
|   register int	c;
 | |
| {
 | |
|   char buf[512+1];
 | |
|   register int base = 10;
 | |
|   register char *p = &buf[0];
 | |
|   register long val = 0;
 | |
|   register int val_c;
 | |
| 
 | |
|   if (c == '0') {
 | |
| 	/* check if next char is an 'x' or an 'X' */
 | |
| 	c = getc(db_in);
 | |
| 	if (c == 'x' || c == 'X') {
 | |
| 		base = 16;
 | |
| 		c = getc(db_in);
 | |
| 	}
 | |
| 	else	base = 8;
 | |
|   }
 | |
|   while (val_c = val_in_base(c, base), val_c >= 0) {
 | |
| 	val = val * base + val_c;
 | |
| 	if (p - buf < 512) *p++ = c;
 | |
| 	c = getc(db_in);
 | |
|   }
 | |
|   if (base == 16 || !((c == '.' || c == 'e' || c == 'E'))) {
 | |
| 	ungetc(c, db_in);
 | |
| 	tok.ival = val;
 | |
| 	return INTEGER;
 | |
|   }
 | |
|   if (c == '.') {
 | |
| 	if (p - buf < 512) *p++ = c;
 | |
| 	c = getc(db_in);
 | |
|   }
 | |
|   while (is_dig(c)) {
 | |
| 	if (p - buf < 512) *p++ = c;
 | |
| 	c = getc(db_in);
 | |
|   }
 | |
|   if (c == 'e' || c == 'E') {
 | |
| 	if (p - buf < 512) *p++ = c;
 | |
| 	c = getc(db_in);
 | |
| 	if (c == '+' || c == '-') {
 | |
| 		if (p - buf < 512) *p++ = c;
 | |
| 		c = getc(db_in);
 | |
| 	}
 | |
| 	if (! is_dig(c)) {
 | |
| 		error("malformed floating constant");
 | |
| 	}
 | |
| 	while (is_dig(c)) {
 | |
| 		if (p - buf < 512) *p++ = c;
 | |
| 		c = getc(db_in);
 | |
| 	}
 | |
|   }
 | |
|   ungetc(c, db_in);
 | |
|   *p++ = 0;
 | |
|   if (p == &buf[512+1]) {
 | |
| 	error("floating point constant too long");
 | |
|   }
 | |
|   tok.fval = atof(buf);
 | |
|   return REAL;
 | |
| }
 | |
| 
 | |
| static int
 | |
| get_token(c)
 | |
|   register int	c;
 | |
| {
 | |
|   switch(c) {
 | |
|   case '`':
 | |
|   case ':':
 | |
|   case ',':
 | |
| 	return c;
 | |
|   case '.':
 | |
| 	return get_number(c);
 | |
|   default:
 | |
| 	error("illegal character 0%o", c);
 | |
| 	return LLlex();
 | |
|   }
 | |
| }
 | |
| 
 | |
| static int
 | |
| quoted(ch)
 | |
|   int	ch;
 | |
| {
 | |
|   /*	quoted() replaces an escaped character sequence by the
 | |
| 	character meant.
 | |
|   */
 | |
|   /* first char after backslash already in ch */
 | |
|   if (!is_oct(ch)) {		/* a quoted char */
 | |
| 	switch (ch) {
 | |
| 	case 'n':
 | |
| 		ch = '\n';
 | |
| 		break;
 | |
| 	case 't':
 | |
| 		ch = '\t';
 | |
| 		break;
 | |
| 	case 'b':
 | |
| 		ch = '\b';
 | |
| 		break;
 | |
| 	case 'r':
 | |
| 		ch = '\r';
 | |
| 		break;
 | |
| 	case 'f':
 | |
| 		ch = '\f';
 | |
| 		break;
 | |
| 	}
 | |
|   }
 | |
|   else {				/* a quoted octal */
 | |
| 	register int oct = 0, cnt = 0;
 | |
| 
 | |
| 	do {
 | |
| 		oct = oct*8 + (ch-'0');
 | |
| 		ch = getc(db_in);
 | |
| 	} while (is_oct(ch) && ++cnt < 3);
 | |
| 	ungetc(ch, db_in);
 | |
| 	ch = oct;
 | |
|   }
 | |
|   return ch&0377;
 | |
| 
 | |
| }
 | |
| 
 | |
| static int 
 | |
| get_string(c)
 | |
|   int	c;
 | |
| {
 | |
|   register int ch;
 | |
|   char buf[512];
 | |
|   register int len = 0;
 | |
| 
 | |
|   while (ch = getc(db_in), ch != c) {
 | |
| 	if (ch == '\n') {
 | |
| 		error("newline in string");
 | |
| 		break;
 | |
| 	}
 | |
| 	if (ch == '\\') {
 | |
| 		ch = getc(db_in);
 | |
| 		ch = quoted(ch);
 | |
| 	}
 | |
| 	buf[len++] = ch;
 | |
|   }
 | |
|   buf[len++] = 0;
 | |
|   tok.str = Salloc(buf, (unsigned) len);
 | |
|   return STRING;
 | |
| }
 | |
| 
 | |
| static int
 | |
| print_op(p)
 | |
|   p_tree	p;
 | |
| {
 | |
|   switch(p->t_oper) {
 | |
|   case OP_UNOP:
 | |
|   	switch(p->t_whichoper) {
 | |
| 	case E_MIN:
 | |
| 		fputs("-", db_out);
 | |
| 		print_node(p->t_args[0], 0);
 | |
| 		break;
 | |
| 	case E_PLUS:
 | |
| 		fputs("+", db_out);
 | |
| 		print_node(p->t_args[0], 0);
 | |
| 		break;
 | |
| 	case E_NOT:
 | |
| 		fputs("~", db_out);
 | |
| 		print_node(p->t_args[0], 0);
 | |
| 		break;
 | |
| 	case E_DEREF:
 | |
| 		fputs("*", db_out);
 | |
| 		print_node(p->t_args[0], 0);
 | |
| 		break;
 | |
| 	}
 | |
| 	break;
 | |
|   case OP_BINOP:
 | |
| 	fputs("(", db_out);
 | |
| 	print_node(p->t_args[0], 0);
 | |
| 	switch(p->t_whichoper) {
 | |
| 	case E_AND:
 | |
| 		fputs("&&", db_out);
 | |
| 		break;
 | |
| 	case E_OR:
 | |
| 		fputs("||", db_out);
 | |
| 		break;
 | |
| 	case E_ZDIV:
 | |
| 		fputs("/", db_out);
 | |
| 		break;
 | |
| 	case E_ZMOD:
 | |
| 		fputs("%", db_out);
 | |
| 		break;
 | |
| 	case E_DIV:
 | |
| 		fputs(" div ", db_out);
 | |
| 		break;
 | |
| 	case E_MOD:
 | |
| 		fputs(" mod ", db_out);
 | |
| 		break;
 | |
| 	case E_IN:
 | |
| 		fputs(" in ", db_out);
 | |
| 		break;
 | |
| 	case E_PLUS:
 | |
| 		fputs("+", db_out);
 | |
| 		break;
 | |
| 	case E_MIN:
 | |
| 		fputs("-", db_out);
 | |
| 		break;
 | |
| 	case E_MUL:
 | |
| 		fputs("*", db_out);
 | |
| 		break;
 | |
| 	case E_EQUAL:
 | |
| 		fputs("==", db_out);
 | |
| 		break;
 | |
| 	case E_NOTEQUAL:
 | |
| 		fputs("!=", db_out);
 | |
| 		break;
 | |
| 	case E_LTEQUAL:
 | |
| 		fputs("<=", db_out);
 | |
| 		break;
 | |
| 	case E_GTEQUAL:
 | |
| 		fputs(">=", db_out);
 | |
| 		break;
 | |
| 	case E_LT:
 | |
| 		fputs("<", db_out);
 | |
| 		break;
 | |
| 	case E_GT:
 | |
| 		fputs(">", db_out);
 | |
| 		break;
 | |
| 	case E_SELECT:
 | |
| 		fputs(".", db_out);
 | |
| 		break;
 | |
| 	}
 | |
| 	print_node(p->t_args[1], 0);
 | |
| 	fputs(")", db_out);
 | |
| 	break;
 | |
|   }
 | |
| }
 |