OpenCores
URL https://opencores.org/ocsvn/open8_urisc/open8_urisc/trunk

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [Open8 Tools/] [open8_src/] [open8_as/] [include_file.c] - Rev 259

Go to most recent revision | Compare with Previous | Blame | View Log

 
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
#include "defines.h"
 
#include "include_file.h"
#include "pass_1.h"
#include "parse.h"
 
 
extern int ind, inz, i, unfolded_size, extra_definitions, d;
extern char *unfolded_buffer, emsg[256], tmp[4096];
extern FILE *file_out_ptr;
 
struct incbin_file_data *incbin_file_data_first = NULL, *ifd_tmp;
struct active_file_info *active_file_info_first = NULL, *active_file_info_last = NULL, *active_file_info_tmp;
struct file_name_info *file_name_info_first = NULL, *file_name_info_last = NULL, *file_name_info_tmp;
char *include_in_tmp = NULL, *tmp_a = NULL;
int include_in_tmp_size = 0, tmp_a_size = 0, file_name_id = 1, open_files = 0;
 
char *full_name = NULL;
int full_name_size = 0;
 
char *include_dir = NULL;
int include_dir_size = 0;
 
char *buffer = NULL;
int size = 0;
 
 
int create_full_name(char *dir, char *name) {
 
  char *t;
  int i;
 
 
  if (dir == NULL && name == NULL)
    return SUCCEEDED;
 
  /* compute the length of the new string */
  i = 0;
  if (dir != NULL)
    i += strlen(dir);
  if (name != NULL)
    i += strlen(name);
  i++;
 
  if (i > full_name_size) {
    t = realloc(full_name, i);
    if (t == NULL) {
      fprintf(stderr, "CREATE_FULL_NAME: Out of memory error.\n");
      return FAILED;
    }
    full_name = t;
    full_name_size = i;
  }
 
  if (dir != NULL) {
    strcpy(full_name, dir);
    if (name != NULL)
      strcat(full_name, name);
  }
  else
    strcpy(full_name, name);
 
  return SUCCEEDED;
}
 
 
int include_file(char *name) {
 
  static int first_load = 0;
  int file_size, id;
  char *tmp_b, *n;
  FILE *f;
 
 
  /* create the full output file name */
  if (create_full_name(include_dir, name) == FAILED)
    return FAILED;
 
  f = fopen(full_name, "rb");
  id = 0;
 
  if (f == NULL && (include_dir == NULL || include_dir[0] == 0)) {
    sprintf(emsg, "Error opening file \"%s\".\n", name);
    if (first_load == 0)
      fprintf(stderr, "INCLUDE_FILE: %s", emsg);
    else
      print_error(emsg, ERROR_INC);
    return FAILED;
  }
 
  /* if failed try to find the file in the current directory */
  if (f == NULL) {
    fprintf(stderr, "%s:%d: ", get_file_name(active_file_info_last->filename_id), active_file_info_last->line_current);
    fprintf(stderr, "INCLUDE_FILE: Could not open \"%s\", trying \"%s\"... ", full_name, name);
    f = fopen(name, "rb");
    id = 1;
  }
 
  if (f == NULL) {
    fprintf(stderr, "not found.\n");
    sprintf(emsg, "Error opening file \"%s\".\n", full_name);
    if (first_load == 0)
      fprintf(stderr, "INCLUDE_FILE: %s", emsg);
    else
      print_error(emsg, ERROR_INC);
    return FAILED;
  }
 
  if (id == 1) {
    fprintf(stderr, "found.\n");
    strcpy(full_name, name);
  }
 
  first_load = 1;
 
  if (extra_definitions == ON) {
    redefine("WLA_FILENAME", 0.0, name, DEFINITION_TYPE_STRING, strlen(name));
    redefine("wla_filename", 0.0, name, DEFINITION_TYPE_STRING, strlen(name));
  }
 
  fseek(f, 0, SEEK_END);
  file_size = ftell(f);
  fseek(f, 0, SEEK_SET);
 
  active_file_info_tmp = malloc(sizeof(struct active_file_info));
  if (active_file_info_tmp == NULL) {
    sprintf(emsg, "Out of memory while trying allocate error tracking data structure for file \"%s\".\n", full_name);
    print_error(emsg, ERROR_INC);
    return FAILED;
  }
  active_file_info_tmp->next = NULL;
 
  if (active_file_info_first == NULL) {
    active_file_info_first = active_file_info_tmp;
    active_file_info_last = active_file_info_tmp;
    active_file_info_tmp->prev = NULL;
  }
  else {
    active_file_info_tmp->prev = active_file_info_last;
    active_file_info_last->next = active_file_info_tmp;
    active_file_info_last = active_file_info_tmp;
  }
 
  active_file_info_tmp->line_current = 1;
 
  /* name */
  file_name_info_tmp = file_name_info_first;
  id = 0;
  while (file_name_info_tmp != NULL) {
    if (strcmp(file_name_info_tmp->name, full_name) == 0) {
      id = file_name_info_tmp->id;
      active_file_info_tmp->filename_id = id;
      break;
    }
    file_name_info_tmp = file_name_info_tmp->next;
  }
 
  if (id == 0) {
    file_name_info_tmp = malloc(sizeof(struct file_name_info));
    n = malloc(strlen(full_name)+1);
    if (file_name_info_tmp == NULL || n == NULL) {
      if (file_name_info_tmp != NULL)
	free(file_name_info_tmp);
      if (n != NULL)
	free(n);
      sprintf(emsg, "Out of memory while trying allocate info structure for file \"%s\".\n", full_name);
      print_error(emsg, ERROR_INC);
      return FAILED;
    }
    file_name_info_tmp->next = NULL;
 
    if (file_name_info_first == NULL) {
      file_name_info_first = file_name_info_tmp;
      file_name_info_last = file_name_info_tmp;
    }
    else {
      file_name_info_last->next = file_name_info_tmp;
      file_name_info_last = file_name_info_tmp;
    }
 
    strcpy(n, full_name);
    file_name_info_tmp->name = n;
    active_file_info_tmp->filename_id = file_name_id;
    file_name_info_tmp->id = file_name_id;
    file_name_id++;
  }
 
  /* reallocate buffer */
  if (include_in_tmp_size < file_size) {
 
    if (include_in_tmp != NULL)
      free(include_in_tmp);
 
    include_in_tmp = malloc(sizeof(char) * file_size);
    if (include_in_tmp == NULL) {
      sprintf(emsg, "Out of memory while trying to allocate room for \"%s\".\n", full_name);
      print_error(emsg, ERROR_INC);
      return FAILED;
    }
 
    include_in_tmp_size = file_size;
  }
 
  /* read the whole file into a buffer */
  fread(include_in_tmp, 1, file_size, f);
  fclose(f);
 
  if (size == 0) {
    buffer = malloc(sizeof(char) * (file_size + 4));
    if (buffer == NULL) {
      sprintf(emsg, "Out of memory while trying to allocate room for \"%s\".\n", full_name);
      print_error(emsg, ERROR_INC);
      return FAILED;
    }
 
    /* preprocess */
    preprocess_file(include_in_tmp, include_in_tmp + file_size, buffer, &size, full_name);
 
    buffer[size++] = 0xA;
    buffer[size++] = '.';
    buffer[size++] = 'E';
    buffer[size++] = ' ';
 
    open_files++;
 
    return SUCCEEDED;
  }
 
  tmp_b = malloc(sizeof(char) * (size + file_size + 4));
  if (tmp_b == NULL) {
    sprintf(emsg, "Out of memory while trying to expand the project to incorporate file \"%s\".\n", full_name);
    print_error(emsg, ERROR_INC);
    return FAILED;
  }
 
  /* reallocate tmp_a */
  if (tmp_a_size < file_size) {
 
    if (tmp_a != NULL)
      free(tmp_a);
 
    tmp_a = malloc(sizeof(char) * (file_size + 4));
    if (tmp_a == NULL) {
      sprintf(emsg, "Out of memory while allocating new room for \"%s\".\n", full_name);
      print_error(emsg, ERROR_INC);
      return FAILED;
    }
 
    tmp_a_size = file_size + 4;
  }
 
  /* preprocess */
  inz = 0;
  preprocess_file(include_in_tmp, include_in_tmp + file_size, tmp_a, &inz, full_name);
 
  tmp_a[inz++] = 0xA;
  tmp_a[inz++] = '.';
  tmp_a[inz++] = 'E';
  tmp_a[inz++] = ' ';
 
  open_files++;
 
  memcpy(tmp_b, buffer, i);
  memcpy(tmp_b + i, tmp_a, inz);
  memcpy(tmp_b + i + inz, buffer + i, size - i);
 
  free(buffer);
 
  size += inz;
  buffer = tmp_b;
 
  return SUCCEEDED;
}
 
 
int incbin_file(char *name, int *id, int *swap, int *skip, int *read) {
 
  struct incbin_file_data *ifd;
  char *in_tmp, *n;
  int file_size, q;
  FILE *f;
 
 
  /* create the full output file name */
  if (create_full_name(include_dir, name) == FAILED)
    return FAILED;
 
  f = fopen(full_name, "rb");
  q = 0;
 
  if (f == NULL && (include_dir == NULL || include_dir[0] == 0)) {
    sprintf(emsg, "Error opening file \"%s\".\n", name);
    print_error(emsg, ERROR_INB);
    return FAILED;
  }
 
  /* if failed try to find the file in the current directory */
  if (f == NULL) {
    fprintf(stderr, "%s:%d: ", get_file_name(active_file_info_last->filename_id), active_file_info_last->line_current);
    fprintf(stderr, "INCBIN_FILE: Could not open \"%s\", trying \"%s\"... ", full_name, name);
    f = fopen(name, "rb");
    q = 1;
  }
 
  if (f == NULL) {
    fprintf(stderr, "not found.\n");
    sprintf(emsg, "Error opening file \"%s\".\n", full_name);
    print_error(emsg, ERROR_INB);
    return FAILED;
  }
 
  if (q == 1) {
    fprintf(stderr, "found.\n");
    strcpy(full_name, name);
  }
 
  fseek(f, 0, SEEK_END);
  file_size = ftell(f);
  fseek(f, 0, SEEK_SET);
 
  ifd = (struct incbin_file_data *)malloc(sizeof(struct incbin_file_data));
  n = malloc(sizeof(char) * (strlen(full_name)+1));
  in_tmp = (char *)malloc(sizeof(char) * file_size);
  if (ifd == NULL || n == NULL || in_tmp == NULL) {
    if (ifd != NULL)
      free(ifd);
    if (n != NULL)
      free(n);
    if (in_tmp != NULL)
      free(in_tmp);
    sprintf(emsg, "Out of memory while allocating data structure for \"%s\".\n", full_name);
    print_error(emsg, ERROR_INB);
    return FAILED;
  }
 
  /* read the whole file into a buffer */
  fread(in_tmp, 1, file_size, f);
  fclose(f);
 
  /* complete the structure */
  ifd->next = NULL;
  ifd->size = file_size;
  strcpy(n, name);
  ifd->name = n;
  ifd->data = in_tmp;
 
  /* find the index */
  q = 0;
  if (incbin_file_data_first != NULL) {
    ifd_tmp = incbin_file_data_first;
    while (ifd_tmp->next != NULL && strcmp(ifd_tmp->name, name) != 0) {
      ifd_tmp = ifd_tmp->next;
      q++;
    }
    if (ifd_tmp->next == NULL) {
      ifd_tmp->next = ifd;
      q++;
    }
  }
  else
    incbin_file_data_first = ifd;
 
  *id = q;
 
  /* SKIP bytes? */
  if (compare_next_token("SKIP", 4) == FAILED)
    *skip = 0;
  else {
    skip_next_token();
    inz = input_number();
    if (inz != SUCCEEDED) {
      print_error(".INCBIN needs the amount of skipped bytes.\n", ERROR_DIR);
      return FAILED;
    }
 
    *skip = d;
  }
 
  /* READ bytes? */
  if (compare_next_token("READ", 4) == FAILED)
    *read = file_size - *skip;
  else {
    skip_next_token();
    inz = input_number();
    if (inz != SUCCEEDED) {
      print_error(".INCBIN needs the amount of bytes for reading.\n", ERROR_DIR);
      return FAILED;
    }
 
    *read = d;
  }
 
  /* SWAP bytes? */
  if (compare_next_token("SWAP", 4) == FAILED)
    *swap = 0;
  else {
    if ((*read & 1) == 1) {
      sprintf(emsg, "File \"%s\" size is odd (%d)! Cannot perform SWAP.\n", full_name, *read);
      print_error(emsg, ERROR_INB);
      return FAILED;
    }
    *swap = 1;
    skip_next_token();
  }
 
  /* FSIZE? */
  if (compare_next_token("FSIZE", 5) == SUCCEEDED) {
    skip_next_token();
 
    /* get the definition label */
    if (get_next_token() == FAILED)
      return FAILED;
 
    add_a_new_definition(tmp, (double)file_size, NULL, DEFINITION_TYPE_VALUE, 0);
  }
 
  if (*skip + *read > file_size) {
    sprintf(emsg, "Overreading file \"%s\".\n", full_name);
    print_error(emsg, ERROR_INB);
    return FAILED;
  }
 
  return SUCCEEDED;
}
 
 
char get_file_name_error[] = "GET_FILE_NAME: Internal error.";
 
 
char *get_file_name(int id) {
 
  struct file_name_info *f;
 
 
  f = file_name_info_first;
  while (f != NULL) {
    if (id == f->id)
      return f->name;
    f = f->next;
  }
 
  return get_file_name_error;
}
 
 
int print_file_names(void) {
 
  struct incbin_file_data *d;
  struct file_name_info *f;
 
 
  f = file_name_info_first;
  d = incbin_file_data_first;
 
  /* handle the main file name differently */
  if (f != NULL) {
    if (f->next != NULL || d != NULL)
      fprintf(stderr, "%s \\\n", f->name);
    else
      fprintf(stderr, "%s\n", f->name);
    f = f->next;
  }
 
  /* included files */
  while (f != NULL) {
    if (f->next != NULL || d != NULL)
      fprintf(stderr, "\t%s \\\n", f->name);
    else
      fprintf(stderr, "\t%s\n", f->name);
    f = f->next;
  }
 
  /* incbin files */
  while (d != NULL) {
    if (d->next != NULL)
      fprintf(stderr, "\t%s \\\n", d->name);
    else
      fprintf(stderr, "\t%s\n", d->name);
    d = d->next;
  }
 
  return SUCCEEDED;
}
 
 
/* the mystery preprocessor - touch it and prepare for trouble ;) the preprocessor
   removes as much white space as possible from the source file. this is to make
   the parsing of the file, that follows, simpler. */
int preprocess_file(char *c, char *d, char *o, int *s, char *f) {
 
  register int t = 0, z = 0;
#if defined(W65816) || defined(SPC700)
  register int u = 0;
#endif
  char *e;
 
 
  e = o + (*s);
  while (c < d) {
    switch (*c) {
    case ';':
      /* clear a commented line */
      c++;
      for ( ; c < d && *c != 0x0A && *c != 0x0D; c++);
      e--;
      for ( ; e > o && *e == ' '; e--);
      if (e < o)
	e = o;
      else if (*e != ' ')
	e++;
      break;
    case '*':
      if (t == 0) {
	/* clear a commented line */
	c++;
	for ( ; c < d && *c != 0x0A && *c != 0x0D; c++);
      }
      else {
	/* multiplication! */
	c++;
	*e = '*';
	e++;
	t = 1;
      }
      break;
    case '/':
      if (*(c + 1) == '*') {
	/* remove an ANSI C -style block comment */
	t = 0;
	c += 2;
	while (t == 0) {
	  for ( ; c < d && *c != '/' && *c != 0x0A; c++);
	  if (c >= d) {
	    sprintf(emsg, "Comment wasn't terminated properly in file \"%s\".\n", f);
	    print_error(emsg, ERROR_INC);
	    return FAILED;
	  }
	  if (*c == 0x0A) {
	    *e = 0x0A;
	    e++;
	  }
	  if (*c == '/' && *(c - 1) == '*') {
	    t = 1;
	  }
	  c++;
	}
	e--;
	for ( ; e > o && *e == ' '; e--);
	if (e < o)
	  e = o;
	else if (*e != ' ')
	  e++;
      }
      else {
	c++;
	*e = '/';
	e++;
	t = 1;
      }
      break;
    case ':':
      /* finding a label resets the counters */
      c++;
      *e = ':';
      e++;
      t = 0;
      break;
    case 0x09:
    case ' ':
      /* remove extra white space */
      c++;
      *e = ' ';
      e++;
      for ( ; c < d && (*c == ' ' || *c == 0x09); c++);
      t = 1;
      if (z == 1)
	z = 2;
      break;
    case 0x0A:
      /* take away white space from the end of the line */
      c++;
      e--;
      for ( ; *e == ' '; e--);
      e++;
      *e = 0x0A;
      e++;
      t = 0;
      z = 0;
#if defined(W65816) || defined(SPC700)
      u = 0;
#endif
      break;
    case 0x0D:
      c++;
      break;
    case '\'':
      if (*(c + 2) == '\'') {
	*e = '\'';
	c++;
	e++;
	*e = *c;
	c++;
	e++;
	*e = '\'';
	c++;
	e++;
      }
      else {
	*e = '\'';
	c++;
	e++;
      }
      t = 1;
      break;
    case '"':
      /* don't alter the strings */
      *e = '"';
      c++;
      e++;
      t = 0;
      while (t == 0) {
	for ( ; c < d && *c != '"'; ) {
	  *e = *c;
	  c++;
	  e++;
	}
	if (*c == '"' && *(c - 1) != '\\')
	  t = 1;
	else {
	  *e = '"';
	  c++;
	  e++;
	}
      }
      *e = '"';
      c++;
      e++;
      break;
#if !defined(W65816) && !defined(SPC700)
    case '[':
      /* change '[' to '(' */
#endif
    case '(':
      *e = '(';
      c++;
      e++;
      for ( ; c < d && (*c == ' ' || *c == 0x09); c++);
      t = 1;
      break;
#if !defined(W65816) && !defined(SPC700)
    case ']':
      /* change ']' to ')' */
#endif
    case ')':
      /* go back? */
      if (t == 1 && *(e - 1) == ' ')
	e--;
      *e = ')';
      c++;
      e++;
      t = 1;
      break;
#if defined(W65816) || defined(SPC700)
    case '[':
      *e = *c;
      c++;
      e++;
      t = 1;
      u = 1;
      break;
#endif
    case ',':
    case '+':
    case '-':
      if (t == 0) {
	for ( ; c < d && (*c == '+' || *c == '-'); c++, e++)
	  *e = *c;
	t = 1;
      }
      else {
#if defined(W65816) || defined(SPC700)
	/* go back? */
	if (*(e - 1) == ' ' && u == 1)
	  e--;
#else
	/* go back? */
	if ((z == 3 || *c == ',') && *(e - 1) == ' ')
	  e--;
#endif
	*e = *c;
	c++;
	e++;
	for ( ; c < d && (*c == ' ' || *c == 0x09); c++);
	t = 1;
      }
      break;
    default:
      *e = *c;
      c++;
      e++;
      if (z == 0)
	z = 1;
      else if (z == 2)
	z = 3;
      t = 1;
      break;
    }
  }
 
  *s = e - o;
 
  return SUCCEEDED;
}
 

Go to most recent revision | Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.