#include <nidl.h>
#include <errors.h>
#include <nametbl.h>
#include <frontend.h>
#include <message.h>
#include <nidlmsg.h>
#include <driver.h>
#define MAX_LINE_LEN 256
#define WHERE_TEXT_LEN 20
#define MAX_WARNINGS 5
#define MAX_ERROR_FILES 10
typedef struct error_log_rec_t
{
STRTAB_str_t filename;
int lineno;
long msg_id;
char *arg1, *arg2, *arg3, *arg4, *arg5;
union
{
struct
{
struct error_log_rec_t *left;
struct error_log_rec_t *right;
} asBinTree;
struct
{
struct error_log_rec_t *next;
} asList;
} links;
struct error_log_rec_t *first_this_line;
struct error_log_rec_t *last_this_line;
} error_log_rec_t;
FILE **yyin_p;
int *yylineno_p;
int *yynerrs_p;
char *yytext_p;
boolean ERR_no_warnings;
static int warnings = 0;
static STRTAB_str_t error_files[MAX_ERROR_FILES];
static int error_file_count = 0;
static int last_error_line = 0;
static char *current_file = NULL;
error_log_rec_t *errors = NULL;
int error_count = 0;
STRTAB_str_t error_file_name_id;
extern void sysdep_cleanup_temp (
void
);
void yywhere
(
void
)
{
boolean have_text = false;
int text_len = 0;
int lineno;
long msg_id;
char *near_text;
STRTAB_str_t string_id;
lineno = *yylineno_p;
if (*yytext_p)
{
for (text_len = 0; text_len < WHERE_TEXT_LEN; ++text_len)
if (!yytext_p[text_len] || yytext_p[text_len] == '\n')
break;
if (text_len > 0)
{
have_text = true;
lineno = lineno - (*yytext_p == '\n' || ! *yytext_p);
}
}
if (have_text)
{
string_id = STRTAB_add_string(yytext_p);
STRTAB_str_to_string(string_id, &near_text);
}
if (have_text)
{
if (feof(*yyin_p))
msg_id = NIDL_EOFNEAR;
else
msg_id = NIDL_SYNTAXNEAR;
}
else
{
if (feof(*yyin_p))
msg_id = NIDL_EOF;
else
msg_id = NIDL_SYNTAXNEAR;
}
log_error(lineno, msg_id, text_len, near_text);
}
void yyerror
(
char *message
)
{
static int list = 0;
if (message || !list)
{
(*yynerrs_p)++;
yywhere();
if (strcmp(message,"syntax error") != 0)
{
fputs(message, stderr);
putc('\n', stderr);
return;
}
return;
}
putc('\n', stderr);
list = 0;
}
static error_log_rec_t *alloc_log_rec
(
STRTAB_str_t filename,
int lineno,
long msg_id,
char *arg1,
char *arg2,
char *arg3,
char *arg4,
char *arg5
)
{
error_log_rec_t *log_rec_p;
int i;
log_rec_p = (error_log_rec_t *) MALLOC(sizeof(error_log_rec_t));
log_rec_p->lineno = lineno;
log_rec_p->filename = filename;
log_rec_p->msg_id = msg_id;
log_rec_p->arg1 = arg1;
log_rec_p->arg2 = arg2;
log_rec_p->arg3 = arg3;
log_rec_p->arg4 = arg4;
log_rec_p->arg5 = arg5;
log_rec_p->first_this_line = 0;
log_rec_p->last_this_line = 0;
log_rec_p->links.asBinTree.left = 0;
log_rec_p->links.asBinTree.right = 0;
log_rec_p->links.asList.next = 0;
for (i = 0; i < error_file_count; i++)
if (error_files[i] == filename) break;
if (i == error_file_count)
error_files[error_file_count++] = filename;
if (error_file_count >= MAX_ERROR_FILES) error_file_count--;
return log_rec_p;
}
static void free_log_rec
(
error_log_rec_t *log_rec_p
)
{
if (log_rec_p->links.asBinTree.left != NULL)
{
free_log_rec(log_rec_p->links.asBinTree.left);
log_rec_p->links.asBinTree.left = NULL;
}
if (log_rec_p->links.asBinTree.right != NULL)
{
free_log_rec(log_rec_p->links.asBinTree.right);
log_rec_p->links.asBinTree.right = NULL;
}
while (log_rec_p->first_this_line != NULL)
{
error_log_rec_t *ep;
ep = log_rec_p->first_this_line;
log_rec_p->first_this_line = log_rec_p->links.asList.next;
FREE(ep);
}
FREE(log_rec_p);
}
static void queue_error
(
error_log_rec_t *log_rec_p,
STRTAB_str_t filename,
long msg_id,
char *arg1,
char *arg2,
char *arg3,
char *arg4,
char *arg5
)
{
error_log_rec_t *new_log_rec_p;
new_log_rec_p = alloc_log_rec(filename, log_rec_p->lineno, msg_id, arg1, arg2, arg3, arg4, arg5);
if (log_rec_p->first_this_line == NULL)
{
log_rec_p->first_this_line = (struct error_log_rec_t *) new_log_rec_p;
log_rec_p->last_this_line = (struct error_log_rec_t *) new_log_rec_p;
return;
}
log_rec_p->last_this_line->links.asList.next =
(struct error_log_rec_t *) new_log_rec_p;
log_rec_p->last_this_line =
(struct error_log_rec_t *) new_log_rec_p;
}
static void add_error_log_rec
(
error_log_rec_t *log_rec_p,
STRTAB_str_t filename,
int lineno,
long msg_id,
char *arg1,
char *arg2,
char *arg3,
char *arg4,
char *arg5
)
{
if (log_rec_p->lineno < lineno)
{
if (log_rec_p->links.asBinTree.right != NULL)
add_error_log_rec(log_rec_p->links.asBinTree.right, filename, lineno,
msg_id, arg1, arg2, arg3, arg4, arg5);
else
log_rec_p->links.asBinTree.right = alloc_log_rec(filename, lineno,
msg_id, arg1, arg2, arg3, arg4, arg5);
return;
}
if (log_rec_p->lineno > lineno)
{
if (log_rec_p->links.asBinTree.left != NULL)
add_error_log_rec(log_rec_p->links.asBinTree.left, filename, lineno,
msg_id, arg1, arg2, arg3, arg4, arg5);
else
log_rec_p->links.asBinTree.left = alloc_log_rec(filename, lineno,
msg_id, arg1, arg2, arg3, arg4, arg5);
return;
}
if (log_rec_p->lineno == lineno)
queue_error(log_rec_p, filename, msg_id, arg1, arg2, arg3, arg4, arg5);
}
void log_source_error
(
STRTAB_str_t filename,
int lineno,
long msg_id,
char *arg1,
char *arg2,
char *arg3,
char *arg4,
char *arg5
)
{
++error_count;
if (errors == NULL)
errors = alloc_log_rec(filename, lineno, msg_id, (char *)arg1, (char *)arg2, (char *)arg3, (char *)arg4, (char *)arg5);
else
add_error_log_rec(errors, filename, lineno, msg_id, (char *)arg1, (char *)arg2, (char *)arg3, (char *)arg4, (char *)arg5);
}
void log_source_warning
(
STRTAB_str_t filename,
int lineno,
long msg_id,
char *arg1,
char *arg2,
char *arg3,
char *arg4,
char *arg5
)
{
if (ERR_no_warnings)
return;
++warnings;
if (errors == NULL)
errors = alloc_log_rec(filename, lineno, msg_id, (char *)arg1, (char *)arg2, (char *)arg3, (char *)arg4, (char *)arg5);
else
add_error_log_rec(errors, filename, lineno, msg_id, (char *)arg1, (char *)arg2, (char *)arg3, (char *)arg4, (char *)arg5);
}
void log_error
(
int lineno,
long msg_id,
char *arg1,
char *arg2,
char *arg3,
char *arg4,
char *arg5
)
{
log_source_error (error_file_name_id, lineno, msg_id, arg1, arg2, arg3, arg4, arg5);
}
void log_warning
(
int lineno,
long msg_id,
char *arg1,
char *arg2,
char *arg3,
char *arg4,
char *arg5
)
{
log_source_warning (error_file_name_id, lineno, msg_id, arg1, arg2, arg3, arg4, arg5);
}
void seek_for_line
(
FILE *source_file,
int lineno,
char *source_line
)
{
int lines_to_skip;
int i;
if (source_file == NULL)
{
source_line[0] = 0;
return;
}
lines_to_skip = lineno - last_error_line;
for (i=0; i<lines_to_skip; i++)
(void) fgets(source_line, MAX_LINE_LEN, source_file);
i = strlen(source_line) - 1;
if (source_line[i] == '\n')
source_line[i] = '\0';
last_error_line = lineno;
}
void print_errors_for_line
(
FILE *fd,
char *source,
STRTAB_str_t source_id,
error_log_rec_t *log_rec_ptr
)
{
char source_line[MAX_LINE_LEN];
boolean source_printed = false;
error_log_rec_t *erp;
if (source_id == log_rec_ptr->filename)
{
source_printed = true;
seek_for_line(fd, log_rec_ptr->lineno, source_line);
message_print(
NIDL_FILESOURCE, source, log_rec_ptr->lineno, source_line
);
message_print(
log_rec_ptr->msg_id, log_rec_ptr->arg1, log_rec_ptr->arg2,
log_rec_ptr->arg3, log_rec_ptr->arg4, log_rec_ptr->arg5
);
}
for (erp = log_rec_ptr->first_this_line; erp; erp=erp->links.asList.next)
{
if (source_id == erp->filename)
{
if (!source_printed)
{
source_printed = true;
seek_for_line(fd, log_rec_ptr->lineno, source_line);
message_print(
NIDL_FILESOURCE, source, log_rec_ptr->lineno, source_line
);
}
message_print(
erp->msg_id, erp->arg1, erp->arg2, erp->arg3, erp->arg4, erp->arg5
);
}
}
}
void print_error_messages
(
FILE *fd,
char *source,
STRTAB_str_t source_id,
error_log_rec_t *log_rec_ptr
)
{
if (log_rec_ptr->links.asBinTree.left != NULL)
print_error_messages(fd, source, source_id, log_rec_ptr->links.asBinTree.left);
print_errors_for_line(fd, source, source_id, log_rec_ptr);
if (log_rec_ptr->links.asBinTree.right != NULL)
print_error_messages(fd, source, source_id, log_rec_ptr->links.asBinTree.right);
}
boolean print_errors
(
void
)
{
FILE *fd;
char *fn;
int i;
STRTAB_str_t source_id;
error_log_rec_t *error_root;
if (errors == NULL) return 0;
error_root = errors;
errors = NULL;
for (i = 0; i < error_file_count; i++)
{
source_id = error_files[i];
STRTAB_str_to_string(source_id, &fn);
fd = fopen(fn, "r");
print_error_messages(fd, fn, source_id, error_root);
last_error_line = 0;
}
free_log_rec(error_root);
error_file_count = 0;
return (error_file_count != 0);
}
void error
(
long msg_id,
char *arg1,
char *arg2,
char *arg3,
char *arg4,
char *arg5
)
{
if (current_file)
message_print(NIDL_LINEFILE, current_file, *yylineno_p);
message_print(msg_id, arg1, arg2, arg3, arg4, arg5);
#ifndef HASPOPEN
sysdep_cleanup_temp();
#endif
nidl_terminate();
}
void error_list
(
int vecsize,
idl_error_list_p errvec,
boolean exitflag
)
{
int i;
if (current_file)
message_print(NIDL_LINEFILE, current_file, *yylineno_p);
for (i = 0; i < vecsize; i++)
message_print(errvec[i].msg_id, errvec[i].arg1, errvec[i].arg2,
errvec[i].arg3, errvec[i].arg4, errvec[i].arg5);
if (!exitflag) return;
#ifndef HASPOPEN
sysdep_cleanup_temp();
#endif
nidl_terminate();
}
void warning
(
long msg_id,
char *arg1,
char *arg2,
char *arg3,
char *arg4,
char *arg5
)
{
if (ERR_no_warnings)
return;
if (current_file)
message_print(NIDL_LINEFILE, current_file, *yylineno_p);
message_print(msg_id, arg1, arg2, arg3, arg4, arg5);
if (++warnings > MAX_WARNINGS)
{
message_print(NIDL_MAXWARN, MAX_WARNINGS);
nidl_terminate();
}
}
void set_name_for_errors
(
char *filename
)
{
if (filename != NULL)
{
error_file_name_id = STRTAB_add_string(filename);
STRTAB_str_to_string(error_file_name_id,¤t_file);
}
else current_file = NULL;
}
void inq_name_for_errors
(
char *name
)
{
if (current_file)
strcpy(name, current_file);
else
*name = '\0';
}