/*
    fd2pragma.h

    This is a small little hack which converts fd-files to pragmas readable
    by the Aztec-C-Compiler or include files readable by the Aztec-Assembler.
    Use it as you want.

    Computer: Amiga 1200			Compiler: Aztec-C V5.0a
							  Dice 2.07.54 (3.0)

    Author:	Jochen Wiedmann
		Am Eisteich 9
	  72555 Metzingen (Germany)
		Tel. 07123 / 14881
		Internet: wiedmann@mailserv.zdv.uni-tuebingen.de
*/

#define FALSE (0)
#define TRUE (!FALSE)

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>




void Usage(void)

{ fprintf(stderr,
	  "Usage: fd2pragma fdfile/a,pragmafile/a,assembler/s\n\n");
  fprintf(stderr, "The program reads the given fd-file and converts ");
  fprintf(stderr, "into pragmas that\n");
  fprintf(stderr, "can be read by the Aztec-Compiler.\n");
  exit (1);
}




void main (int argc, char **argv)

  { FILE *fd, *pragm;
    char *ptr, *ptr2;
    char *defptr;
    char *fdfile = NULL, *pragmafile = NULL;
    int assembler = FALSE;
    int bias = 0;
    int linenum = 0;
    int numargs;
    int public = TRUE;
    int i, deflen;
    char line[512];
    char baseptr[512];

    /*	No WBStartup	*/
    if (argc == 0)
      { exit(0);
      }

    for (i = 1;  i < argc;  i++)
    { if(stricmp(argv[i], "assembler") == 0)
      { assembler = TRUE;
      }
      else if (fdfile == NULL)
      { fdfile = argv[i];
      }
      else if (pragmafile == NULL)
      { pragmafile = argv[i];
      }
      else
      { Usage();
      }
    }

    if (!fdfile  ||  !pragmafile)
    { Usage();
    }

    if ((fd = fopen (fdfile, "r"))  ==  NULL)
      { fprintf(stderr, "Cannot open %s as input!\n", fdfile);
      }
    if ((pragm = fopen(pragmafile, "w"))  ==  NULL)
      { fprintf(stderr, "Cannot open %s as output!\n", pragmafile);
      }
    defptr = fdfile;
    if (index(defptr, ':')  !=  NULL)
      { defptr = index(defptr, ':') + 1;
      }
    if (rindex(defptr, '/')  !=  NULL)
      { defptr = rindex(defptr, '/') + 1;
      }
    if (!assembler  &&
	(deflen = strlen(defptr)-7) >= 0  &&
	strnicmp(defptr+deflen, "_lib.fd", 7) == 0)
      { fprintf(pragm, "#ifndef PRAGMAS_");
	for (i = 0;  i < deflen;  i++)
	  { putc(toupper((int) defptr[i]), pragm);
	  }
	fprintf(pragm, "_LIB_H\n#define PRAGMAS_");
	for (i = 0;  i < deflen;  i++)
	  { putc(toupper((int) defptr[i]), pragm);
	  }
	fprintf(pragm, "_LIB_H\n\n#ifndef CLIB_");
	for (i = 0;  i < deflen;  i++)
	  { putc(toupper((int) defptr[i]), pragm);
	  }
	fprintf(pragm, "_PROTOS_H\n#include <clib/");
	for (i = 0;  i < deflen;  i++)
	  { putc(tolower((int) defptr[i]), pragm);
	  }
	fprintf(pragm, "_protos.h>\n#endif\n\n");
      }
    else
      { defptr = NULL;
      }



    *baseptr = '\0';
    while(fgets(line, sizeof(line), fd)  !=  NULL)
      { ++linenum;

	if(strlen(line) > 0  &&  line[strlen(line)-1] != '\n')
	  { fprintf(stderr, "Error: line %d too long!\n", linenum);
	  }
	line[strlen(line)-1] = '\0';    /*  Remove LF   */

	if(*line == '*')
	  { /*	Ignore any comments */
	  }
	else if (strncmp(line, "##base", 6)  ==  0)
	  { if (*baseptr == '\0')
	      { if ((ptr = strchr(line, '_'))  ==  NULL)
		  { fprintf(stderr,
			    "Line %d: Library-Basepointer in unexpected format!\n",
			    linenum);
		  }
		strcpy(baseptr, ++ptr);
		if (!assembler)
		{ printf("Using Library-Basepointer %s.\n", baseptr);
		}
	      }
	    else
	      { fprintf(stderr, "Line %d: Library-Baseptr already set!\n",
			linenum);
	      }
	  }
	else if (strncmp(line, "##bias", 6)  ==  0)
	  { if ((bias = atol(line+6)) <= 0  ||  bias % 6 != 0)
	      { fprintf (stderr, "Line %d: Bias has an uncorrect value!\n");
	      }
	  }
	else if (strncmp(line, "##public", 8)  ==  0)
	  { public = TRUE;
	  }
	else if (strncmp(line, "##private", 9)  ==  0)
	  { public = FALSE;
	  }
	else if (strncmp(line, "##end", 5)  ==  0)
	  { if (defptr)
	      { fprintf(pragm,"\n#endif  /*  PRAGMAS_");
		for (i = 0;  i < deflen;  i++)
		  { putc(toupper((int) defptr[i]), pragm);
		  }
		fprintf(pragm, "_LIB_H  */\n");
	      }
	    fclose(fd);
	    fclose(pragm);
	    exit(0);
	  }
	else if (*line == '#')
	  { fprintf(stderr, "Line %d: Unknown command!\n", linenum);
	  }
	else
	  { if (public)
	      { if (!assembler  &&  *baseptr == '\0')
		  { fprintf(stderr, "Line %d: Library-Basepointer not set!\n",
			    linenum);
		  }
		if (bias == 0)
		  { fprintf(stderr, "Line %d: Bias not set!\n", linenum);
		  }
		if ((ptr = strchr(line, '('))  ==  NULL)
		  { fprintf(stderr, "Line %d: Unknown function-format!\n",
			    linenum);

		  }
		else
		  { *ptr = '\0';
		    if (assembler)
		    { fprintf(pragm, "\txdef\t_LVO%s\n_LVO%s\tequ\t%d\n",
			      line, line, -bias);
		    }
		    else
		    { fprintf(pragm, "#pragma amicall(%s, 0x%x, %s(",
			      baseptr, bias, line);
		      if ((ptr = strchr(ptr+1, '('))  ==  NULL)
		      { fprintf(stderr, "Line %d: Unknown format!\n",
				linenum);
		      }
		      else
		      { char c = '\0';

			++ptr;
			numargs = 0;
			do
			{ if ((ptr2 = strchr(ptr, '/'))  !=  NULL  ||
			      (ptr2 = strchr(ptr, ')'))  !=  NULL)
			  { c = *ptr2;
			    if (ptr < ptr2)
			    { *ptr2 = '\0';
			      fprintf(pragm, "%s%s",
				      (numargs == 0) ? "" : ",",
				      ptr);
			    }
			    ptr = ptr2+1;
			    numargs++;
			  }
			  else
			  { fprintf(stderr, "Line %d: Unknown format!\n",
				    linenum);
			    break;
			  }
			}
			while (c != ')');
			fprintf(pragm, "))\n");
		      }
		    }
		  }
	      }
	    bias += 6;
	  }
      }

    fprintf(stderr, "Missing ##end!\n");
    fclose(fd);
    fclose(pragm);
    exit(0);
  }
