ack/util/grind/c.c

604 lines
8.8 KiB
C
Raw Normal View History

1990-09-14 14:37:26 +00:00
/* $Header$ */
/* Language dependant support; this one is for C */
#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(),
1990-09-19 14:31:12 +00:00
print_char(),
1990-09-14 14:37:26 +00:00
get_number(),
get_string(),
get_token(),
print_op(),
1990-09-19 14:31:12 +00:00
unop_prio(),
1990-09-20 17:51:14 +00:00
binop_prio(),
fix_bin_to_pref();
1990-09-14 14:37:26 +00:00
static long
array_elsize();
static struct langdep c = {
0,
"%ld",
"0%lo",
"0x%lX",
"%lu",
"0x%lX",
1990-10-17 17:00:03 +00:00
"%.14g",
1990-09-14 14:37:26 +00:00
"{",
"}",
"{",
"}",
"{",
"}",
print_string,
1990-09-19 14:31:12 +00:00
print_char,
1990-09-14 14:37:26 +00:00
array_elsize,
1990-09-19 14:31:12 +00:00
binop_prio,
unop_prio,
1990-09-14 14:37:26 +00:00
get_string,
get_name,
get_number,
get_token,
1990-09-20 17:51:14 +00:00
print_op,
fix_bin_to_pref
1990-09-14 14:37:26 +00:00
};
struct langdep *c_dep = &c;
static int
1990-11-06 12:23:41 +00:00
printchar(f, c, esc)
FILE *f;
int c;
{
1990-10-31 15:56:51 +00:00
c &= 0377;
switch(c) {
case '\n':
1990-11-06 12:23:41 +00:00
fputs("\\n", f);
break;
case '\t':
1990-11-06 12:23:41 +00:00
fputs("\\t", f);
break;
case '\b':
1990-11-06 12:23:41 +00:00
fputs("\\b", f);
break;
case '\r':
1990-11-06 12:23:41 +00:00
fputs("\\r", f);
break;
case '\f':
1990-11-06 12:23:41 +00:00
fputs("\\f", f);
break;
case '\\':
1990-11-06 12:23:41 +00:00
fputs("\\\\", f);
break;
case '\'':
case '"':
1990-11-06 12:23:41 +00:00
fprintf(f, c == esc ? "\\%c" : "%c", c);
break;
default:
1990-11-06 12:23:41 +00:00
fprintf(f, (c >= 040 && c < 0177) ? "%c" : "\\%03o", c);
break;
}
}
1990-09-19 14:31:12 +00:00
static int
print_char(c)
int c;
{
putc('\'', db_out);
1990-11-06 12:23:41 +00:00
printchar(db_out, c, '\'');
putc('\'', db_out);
1990-09-19 14:31:12 +00:00
}
1990-09-14 14:37:26 +00:00
static int
1990-11-06 12:23:41 +00:00
print_string(f, s, len)
FILE *f;
1990-09-14 14:37:26 +00:00
char *s;
int len;
{
register char *str = s;
1990-11-06 12:23:41 +00:00
putc('"', f);
while (*str && len-- > 0) printchar(f, *str++, '"');
putc('"', f);
1990-09-14 14:37:26 +00:00
}
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;
}
static int
1990-09-19 14:31:12 +00:00
unop_prio(op)
1990-09-14 14:37:26 +00:00
int op;
{
switch(op) {
1990-09-19 14:31:12 +00:00
case E_NOT:
case E_BNOT:
case E_MIN:
1990-10-01 11:44:27 +00:00
case E_DEREF:
1990-09-19 14:31:12 +00:00
case E_PLUS:
1990-10-01 11:44:27 +00:00
case E_ADDR:
1990-09-19 14:31:12 +00:00
return 12;
}
return 1;
}
static int
binop_prio(op)
int op;
{
switch(op) {
case E_OR:
return 2;
case E_AND:
return 3;
case E_BOR:
return 4;
case E_BXOR:
return 5;
case E_BAND:
return 6;
case E_EQUAL:
case E_NOTEQUAL:
return 7;
case E_LT:
case E_LTEQUAL:
case E_GT:
case E_GTEQUAL:
return 8;
case E_LSFT:
case E_RSFT:
return 9;
case E_MIN:
case E_PLUS:
return 10;
case E_MUL:
case E_DIV:
case E_ZDIV:
case E_MOD:
case E_ZMOD:
return 11;
case E_ARRAY:
case E_SELECT:
return 12;
case E_DERSELECT:
return 13;
1990-09-14 14:37:26 +00:00
}
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 '[':
tok.ival = E_ARRAY;
/* fall through */
1990-09-14 14:37:26 +00:00
case '(':
case ')':
case ']':
case '`':
case ':':
case ',':
case '}':
case '{':
case '\\':
1990-09-14 14:37:26 +00:00
return c;
case '.':
tok.ival = E_SELECT;
return SEL_OP;
case '+':
tok.ival = E_PLUS;
return PREF_OR_BIN_OP;
case '-':
1990-09-19 14:31:12 +00:00
c = getc(db_in);
if (c == '>') {
tok.ival = E_DERSELECT;
return BIN_OP;
}
ungetc(c, db_in);
1990-09-14 14:37:26 +00:00
tok.ival = E_MIN;
return PREF_OR_BIN_OP;
case '*':
tok.ival = E_MUL;
return PREF_OR_BIN_OP;
case '/':
tok.ival = E_ZDIV;
return BIN_OP;
case '%':
tok.ival = E_ZMOD;
return BIN_OP;
case '&':
c = getc(db_in);
if (c == '&') {
tok.ival = E_AND;
1990-09-20 17:51:14 +00:00
return BIN_OP;
1990-09-14 14:37:26 +00:00
}
1990-09-20 17:51:14 +00:00
ungetc(c, db_in);
tok.ival = E_BAND;
return PREF_OR_BIN_OP;
1990-09-14 14:37:26 +00:00
case '^':
tok.ival = E_BXOR;
return BIN_OP;
case '|':
c = getc(db_in);
if (c == '|') {
tok.ival = E_OR;
}
else {
ungetc(c, db_in);
tok.ival = E_BOR;
}
return BIN_OP;
case '=':
c = getc(db_in);
if (c == '=') {
}
else {
ungetc(c, db_in);
warning("== assumed");
}
tok.ival = E_EQUAL;
return BIN_OP;
case '<':
c = getc(db_in);
if (c == '=') {
tok.ival = E_LTEQUAL;
return BIN_OP;
}
1990-09-19 14:31:12 +00:00
if (c == '<') {
tok.ival = E_LSFT;
return BIN_OP;
}
1990-09-14 14:37:26 +00:00
ungetc(c, db_in);
tok.ival = E_LT;
return BIN_OP;
case '>':
c = getc(db_in);
if (c == '=') {
tok.ival = E_GTEQUAL;
return BIN_OP;
}
1990-09-19 14:31:12 +00:00
if (c == '>') {
tok.ival = E_RSFT;
return BIN_OP;
}
1990-09-14 14:37:26 +00:00
ungetc(c, db_in);
tok.ival = E_GT;
return BIN_OP;
case '!':
c = getc(db_in);
if (c == '=') {
tok.ival = E_NOTEQUAL;
return BIN_OP;
}
ungetc(c, db_in);
tok.ival = E_NOT;
return PREF_OP;
1990-09-19 14:31:12 +00:00
case '~':
tok.ival = E_BNOT;
return PREF_OP;
1990-09-14 14:37:26 +00:00
default:
error((c >= 040 && c < 0177) ? "%s'%c'" : "%s'\\0%o'", "illegal character ", c);
1990-09-14 14:37:26 +00:00
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");
ungetc(ch, db_in);
1990-09-14 14:37:26 +00:00
break;
}
if (ch == '\\') {
ch = getc(db_in);
ch = quoted(ch);
}
buf[len++] = ch;
}
buf[len++] = 0;
if (c == '\'') {
long val = 0;
ch = 0;
while (buf[ch] != 0) {
val = (val << 8) + (buf[ch++] & 0377);
}
tok.ival = val;
return INTEGER;
}
1990-09-14 14:37:26 +00:00
tok.str = Salloc(buf, (unsigned) len);
return STRING;
}
static int
1990-11-06 12:23:41 +00:00
print_op(f, p)
FILE *f;
1990-09-14 14:37:26 +00:00
p_tree p;
{
switch(p->t_oper) {
case OP_UNOP:
switch(p->t_whichoper) {
case E_MIN:
1990-11-06 12:23:41 +00:00
fputs("-(", f);
print_node(f, p->t_args[0], 0);
putc(')', f);
1990-09-14 14:37:26 +00:00
break;
case E_PLUS:
1990-11-06 12:23:41 +00:00
fputs("+(", f);
print_node(f, p->t_args[0], 0);
putc(')', f);
1990-09-14 14:37:26 +00:00
break;
case E_NOT:
1990-11-06 12:23:41 +00:00
fputs("!(", f);
print_node(f, p->t_args[0], 0);
putc(')', f);
1990-09-14 14:37:26 +00:00
break;
case E_DEREF:
1990-11-06 12:23:41 +00:00
fputs("*(", f);
print_node(f, p->t_args[0], 0);
putc(')', f);
1990-09-14 14:37:26 +00:00
break;
1990-09-19 14:31:12 +00:00
case E_BNOT:
1990-11-06 12:23:41 +00:00
fputs("~(", f);
print_node(f, p->t_args[0], 0);
putc(')', f);
1990-09-19 14:31:12 +00:00
break;
1990-09-20 17:51:14 +00:00
case E_ADDR:
1990-11-06 12:23:41 +00:00
fputs("&(", f);
print_node(f, p->t_args[0], 0);
putc(')', f);
1990-09-20 17:51:14 +00:00
break;
1990-09-14 14:37:26 +00:00
}
break;
case OP_BINOP:
1990-09-19 14:31:12 +00:00
if (p->t_whichoper == E_ARRAY) {
1990-11-06 12:23:41 +00:00
print_node(f, p->t_args[0], 0);
fputs("[", f);
print_node(f, p->t_args[1], 0);
fputs("]", f);
1990-09-19 14:31:12 +00:00
break;
}
if (p->t_whichoper == E_DERSELECT) {
1990-11-06 12:23:41 +00:00
print_node(f, p->t_args[0], 0);
fputs("->", f);
print_node(f, p->t_args[1], 0);
1990-09-19 14:31:12 +00:00
break;
}
if (p->t_whichoper == E_SELECT) {
1990-11-06 12:23:41 +00:00
print_node(f, p->t_args[0], 0);
fputs(".", f);
print_node(f, p->t_args[1], 0);
1990-09-19 14:31:12 +00:00
break;
}
1990-11-06 12:23:41 +00:00
fputs("(", f);
print_node(f, p->t_args[0], 0);
1990-09-14 14:37:26 +00:00
switch(p->t_whichoper) {
1990-09-19 14:31:12 +00:00
case E_LSFT:
1990-11-06 12:23:41 +00:00
fputs("<<", f);
1990-09-19 14:31:12 +00:00
break;
case E_RSFT:
1990-11-06 12:23:41 +00:00
fputs(">>", f);
1990-09-19 14:31:12 +00:00
break;
1990-09-14 14:37:26 +00:00
case E_AND:
1990-11-06 12:23:41 +00:00
fputs("&&", f);
1990-09-14 14:37:26 +00:00
break;
case E_BAND:
1990-11-06 12:23:41 +00:00
fputs("&", f);
1990-09-14 14:37:26 +00:00
break;
case E_OR:
1990-11-06 12:23:41 +00:00
fputs("||", f);
1990-09-14 14:37:26 +00:00
break;
case E_BOR:
1990-11-06 12:23:41 +00:00
fputs("|", f);
1990-09-14 14:37:26 +00:00
break;
case E_BXOR:
1990-11-06 12:23:41 +00:00
fputs("^", f);
1990-09-14 14:37:26 +00:00
break;
case E_ZDIV:
1990-11-06 12:23:41 +00:00
fputs("/", f);
1990-09-14 14:37:26 +00:00
break;
case E_ZMOD:
1990-11-06 12:23:41 +00:00
fputs("%", f);
1990-09-14 14:37:26 +00:00
break;
case E_PLUS:
1990-11-06 12:23:41 +00:00
fputs("+", f);
1990-09-14 14:37:26 +00:00
break;
case E_MIN:
1990-11-06 12:23:41 +00:00
fputs("-", f);
1990-09-14 14:37:26 +00:00
break;
case E_MUL:
1990-11-06 12:23:41 +00:00
fputs("*", f);
1990-09-14 14:37:26 +00:00
break;
case E_EQUAL:
1990-11-06 12:23:41 +00:00
fputs("==", f);
1990-09-14 14:37:26 +00:00
break;
case E_NOTEQUAL:
1990-11-06 12:23:41 +00:00
fputs("!=", f);
1990-09-14 14:37:26 +00:00
break;
case E_LTEQUAL:
1990-11-06 12:23:41 +00:00
fputs("<=", f);
1990-09-14 14:37:26 +00:00
break;
case E_GTEQUAL:
1990-11-06 12:23:41 +00:00
fputs(">=", f);
1990-09-14 14:37:26 +00:00
break;
case E_LT:
1990-11-06 12:23:41 +00:00
fputs("<", f);
1990-09-14 14:37:26 +00:00
break;
case E_GT:
1990-11-06 12:23:41 +00:00
fputs(">", f);
1990-09-14 14:37:26 +00:00
break;
}
1990-11-06 12:23:41 +00:00
print_node(f, p->t_args[1], 0);
fputs(")", f);
1990-09-14 14:37:26 +00:00
break;
}
}
1990-09-20 17:51:14 +00:00
static int
fix_bin_to_pref(p)
p_tree p;
{
switch(p->t_whichoper) {
case E_MUL:
p->t_whichoper = E_DEREF;
break;
case E_BAND:
p->t_whichoper = E_ADDR;
break;
}
}