mknfcts.c

来自「basic.c */ /**//* Project:NeuroBasic, b」· C语言 代码 · 共 539 行

C
539
字号
/****************************************************************//*								*//* Name:	mknfcts.c					*//*								*//* Project:	NeuroBasic, utility program			*//*								*//* Survey:	Creates a C source file containing the global	*//*		neuro-function list and all corresponding	*//*		interface functions. Input files must contain	*//*		only neuro-function prototypes.			*//*		The output files are specified by the last two	*//*		arguments, all other arguments are considered	*//*		as input file names.				*//*								*//* Author:	Urs Mueller					*//*		Electronics Laboratory, ETH Zuerich		*//*		Switzerland					*//*								*//* Created:	July 20, 1994					*//* Modified:	December 4, 1994 (mk)				*//*								*//****************************************************************/#include <stdio.h>#include <stdlib.h>#include <ctype.h>#include <string.h>/* macros *//**********/#define MINT_NAME		"MINT"#define MFLOAT_NAME		"MFLOAT"#define CHAR_NAME		"char"#define VOID_NAME		"void"#define	LIST_MAX		512#define LINE_MAX		512#define TRUE			1#define FALSE			0/* type definitions *//********************/typedef enum{  RT_INVALID, RT_MINT, RT_MFLOAT, RT_VOID} ret_type_t;/* global variables *//********************/int		error_flag;char		*function_list[LIST_MAX];char		*protos_list[LIST_MAX];long		nfunctions = 0;static char *str_upper(char *str)/*=============================*/{  char		*s;    for (s = str; *s != 0; s++)    *s = toupper(*s);  return str;} /* end of str_upper() */static void add_to_string(char *string, char ch, int string_max)/*============================================================*/{  int		i;    i = 0;  while (*string != 0)  {    i++;    string++;  }  if (i < string_max-1)  {    *string++ = ch;    *string = 0;  }  else    string[-1] = -1;			/* mark as false name */} /* end of add_to_string() */static ret_type_t check_ret_name(char *ret_name)/*============================================*/{  if (strcmp(ret_name, MINT_NAME) == 0)		return RT_MINT;  if (strcmp(ret_name, MFLOAT_NAME) == 0)	return RT_MFLOAT;  if (strcmp(ret_name, VOID_NAME) == 0)		return RT_VOID;						return RT_INVALID;} /* end of check_ret_name() */static int is_space(char *pch, FILE *fpt)/*=========================--==========*//* Like library function isspace() but skips comments of the    C source code.*/{  char		c2;    if (isspace(*pch)) return TRUE;  if (*pch != '/') return FALSE;  *pch = fgetc(fpt);  if (*pch != '*')			/* is it a comment? */  {					/* no */    ungetc(*pch, fpt);    return FALSE;  }  else  {					/* skip the comment */    *pch = fgetc(fpt);    do    {      c2 = *pch;      *pch = fgetc(fpt);    } while ((*pch != EOF) && (c2 != '*' || *pch != '/'));    *pch = ' ';			/* replace comment by a real space */    return TRUE;  }} /* end of is_space() */static void scan_header(char *filename)/*===================================*//* Scans all input files and creates a list of function prototypes   and corresponding function names.*/{#define RET_NAME_MAX	32  FILE		*fpt;  char		ch, ret_name[RET_NAME_MAX], *prototype, *fname;  ret_type_t	ret_type;    fpt = fopen(filename, "r");  if (fpt == NULL)  {    printf("ERROR of mknfcts: cannot read header file \"%s\".\n",	   filename);    error_flag = EXIT_FAILURE;    return;  }  ret_name[0] = 0;  ch = fgetc(fpt);  while (ch != EOF)  {    /*===== skipping white space and comments =====*/    while (is_space(&ch, fpt)) ch = fgetc(fpt);    /*===== scanning a word =====*/    ret_type = check_ret_name(ret_name);    ret_name[0] = 0;    while (ch != EOF && ch != '(' && !is_space(&ch, fpt))     {      add_to_string(ret_name, ch, RET_NAME_MAX);      ch = fgetc(fpt);    }    /*===== is it a function prototype? =====*/    while (is_space(&ch, fpt)) ch = fgetc(fpt);    if (ret_type == RT_INVALID || ch != '(')    {						/* not a prototype */      if (ch == '(') ch = fgetc(fpt);      continue;    }    fname = malloc(strlen(ret_name) + 1);    prototype = malloc(LINE_MAX);    if (prototype == NULL || fname == 0)    {      printf("ERROR: Not enough memory to continue.\n");      if (fname != NULL) free(fname);      if (prototype != NULL) free(prototype);      error_flag = TRUE;      break;    }    strcpy(fname, ret_name);    prototype[0] = 0;    switch (ret_type)    {      case RT_MINT:	strcat(prototype, MINT_NAME);      			break;      case RT_MFLOAT:	strcat(prototype, MFLOAT_NAME);      			break;      case RT_VOID:	strcat(prototype, VOID_NAME);      			break;      default:		break;    } /* end of switch () */    strcat(prototype, " ");    strcat(prototype, fname);        while (ch != EOF && ch != ')')    {      add_to_string(prototype, ch, LINE_MAX);      ch = fgetc(fpt);    }    add_to_string(prototype, ch, LINE_MAX);    ch = fgetc(fpt);    add_to_string(prototype, ch, LINE_MAX);    if (prototype[strlen(prototype)-2] == ')'	&& prototype[strlen(prototype)-1] == ';')    {					/* defenitely a prototype */      function_list[nfunctions] = fname;      protos_list[nfunctions] = prototype;      nfunctions++;    }    else    {					/* not a prototype */      free(fname);      free(prototype);    }  }  fclose(fpt);} /* end of scan_header() */static const char *skip_comment(const char *ps)/*===========================================*/{  if (ps[0] == '/' && ps[1] == '*')  {    ps += 2;    while (ps[0] != 0 && (ps[0] != '*' || ps[1] != '/')) ps++;    if (ps[0] != 0) ps++;  }  if (*ps != 0) ps++;  return ps;} /* end of skip_comment() */static void compress_prototypes(void)/*=================================*//* Replaces the real prototype strings by a list of characters   each representing the return type and all parameter types.   v = void   i = MINT   f = MFLOAT   a = variable number of arguments follow*/{  long		fn;  const char	*ps;  char		*pd;  int		var_args;  for (fn = 0; fn < nfunctions; fn++)  {    ps = pd = protos_list[fn];    if (strncmp(MINT_NAME, ps, strlen(MINT_NAME)) == 0)      *pd++ = 'i';				/* MINT */    else if (strncmp(MFLOAT_NAME, ps, strlen(MFLOAT_NAME)) == 0)      *pd++ = 'f';				/* MFLOAT */    else      *pd++ = 'v';				/* void */    while (*ps != 0 && *ps != '(') ps = skip_comment(ps);    if (*ps != 0) ps++;    var_args = FALSE;    while (*ps != 0)    {      while (*ps != 0 && (isspace(*ps) || *ps == '/'))	ps = skip_comment(ps);      if (strncmp(MINT_NAME, ps, strlen(MINT_NAME)) == 0)      {	*pd++ = 'i';				/* MINT */	ps += strlen(MINT_NAME);      }      else if (strncmp(MFLOAT_NAME, ps, strlen(MFLOAT_NAME)) == 0)      {	*pd++ = 'f';				/* MFLOAT */	ps += strlen(MFLOAT_NAME);      }      else if (strncmp(CHAR_NAME, ps, strlen(CHAR_NAME)) == 0)      {						/* char */	*pd++ = 'c';	ps += strlen(CHAR_NAME);      }      while (*ps != 0 && (isspace(*ps) || *ps == '/'))	ps = skip_comment(ps);      var_args = (*ps == '*');      while (*ps != 0 && *ps != ',') ps = skip_comment(ps);      if (*ps != 0) ps++;    }    *pd = 0;				/* terminate string */    if (var_args && strlen(protos_list[fn]) > 3)    {      pd[strlen(pd) - 2] = 'a';      pd[strlen(pd) - 1] = 'a';    }  }} /* end of compress_prototypes() */static void release_memory(void)/*============================*/{  long		i;  for (i = 0; i < nfunctions; i++)	free(function_list[i]);  for (i = 0; i < nfunctions; i++)	free(protos_list[i]);} /* end of release_memory() */static void write_file_header(FILE *fpt)/*====================================*/{  fprintf(fpt, "/*\n");  fprintf(fpt, "   This file was created by mknfcts. ");  fprintf(fpt, "Do not modify it!\n");  fprintf(fpt, "*/\n\n\n");} /* end of write_file_header() */static void write_fct_protos(char *filename)/*========================================*/{  FILE		*ofpt;  long		fct;  char		name[FILENAME_MAX], *pc;  pc = strrchr(filename, '/');  if (pc == NULL) pc = strrchr(filename, '\\');  if (pc == NULL) pc = filename; else pc++;  strcpy(name, pc);  pc = strrchr(name, '.');  if (pc != NULL) *pc = 0;  str_upper(name);  ofpt = fopen(filename, "w");  if (ofpt == NULL)  {    printf("ERROR of mkfcts: cannot open output file \"%s\".\n",	   filename);    error_flag = EXIT_FAILURE;    return;  }  write_file_header(ofpt);  fprintf(ofpt, "\n\n#ifndef __%s__\n#define __%s__\n\n\n",	  name, name);    fprintf(ofpt, "/* Prototypes of neuro-functions */\n");  fprintf(ofpt, "/*********************************/\n\n");  for (fct = 0; fct < nfunctions; fct++)    fprintf(ofpt, "%s\n", protos_list[fct]);  fprintf(ofpt, "\n\n");  fprintf(ofpt, "\n\n#endif /* __%s__ */\n", name);  if (ferror(ofpt))  {    printf("ERROR of mknfcts: Write error on \"%s\".\n", filename);    error_flag = EXIT_FAILURE;  }  fclose(ofpt);} /* end fo write_fct_protos() */int main(int argc, char *argv[])/******************************/{  int		arg, j;  long		nargs, fct;  FILE		*ofpt;    if (argc < 4)  {    printf("Usage: mknfcts <input1> <input2> ... <.c-output> ");    printf("<.h-output>\n");    return EXIT_FAILURE;  }  ofpt = fopen(argv[argc-2], "w");  if (ofpt == NULL)  {    printf("ERROR of mkfcts: cannot open output file \"%s\".\n",	   argv[argc-1]);    return EXIT_FAILURE;  }  error_flag = EXIT_SUCCESS;  write_file_header(ofpt);  fprintf(ofpt, "#include <stdio.h>\n");  fprintf(ofpt, "#include <musiclib.h>\n\n");  fprintf(ofpt, "#include \"allnfcts.h\"\n");  fprintf(ofpt, "#include \"basic.h\"\n\n\n");  /*===== scan header files and create prototype list =====*/  for (arg = 1; arg < argc-2; arg++)    scan_header(argv[arg]);  /*===== write function prototypes =====*/  write_fct_protos(argv[argc-1]);  /*===== make interface code for neuro-functions =====*/  compress_prototypes();  fprintf(ofpt, "/* interface functions */\n");  fprintf(ofpt, "/***********************/\n\n");  for (fct = 0; fct < nfunctions; fct++)  {    fprintf(ofpt, "static void if_%s(b_stack_t **pb_sp)\n{\n",	    function_list[fct]);    if (strchr(protos_list[fct], 'c') != NULL)    {      fprintf(ofpt, "  message_t msg;\n");      fprintf(ofpt, "  MINT str_bufa[STR_BUF_MAX], *pa, i;\n");      fprintf(ofpt, "  char *pb;\n");    }    for (j = 0; j < strlen(protos_list[fct]) - 1; j++)    {      if (protos_list[fct][j+1] == 'c')      {	fprintf(ofpt, "  char str_buf%db[STR_BUF_MAX];\n", j);      }    }    if (protos_list[fct][strlen(protos_list[fct])-1] == 'a')    {      fprintf(ofpt, "  MINT nargs;\n");      fprintf(ofpt, "  nargs = ((*pb_sp)[-1].i - %ld);\n",	      strlen(protos_list[fct]) - 3);    }    fprintf(ofpt, "  (*pb_sp) -= (*pb_sp)[-1].i;\n");    /* get strings from host */    for (j = 0; j < strlen(protos_list[fct]) - 1; j++)    {      if (protos_list[fct][j+1] == 'c')      {	fprintf(ofpt, "  msg[0].i = C_SENDSTRING;\n");	fprintf(ofpt, "  msg[1].i = (MINT)(*pb_sp)[%d].f;\n", j - 1);	fprintf(ofpt, "  Wr_to_host(msg, sizeof(msg), WR_ONE);\n");	fprintf(ofpt,	  "  Rd_from_host(str_bufa, sizeof(str_bufa), RD_ALL);\n");	fprintf(ofpt, "  pa = str_bufa;\n");	fprintf(ofpt, "  pb = str_buf%db;\n", j);	fprintf(ofpt, "  for (i = 0; i < STR_BUF_MAX; i++)\n");	fprintf(ofpt, "    *pb++ = *pa++;\n");      }    }    fprintf(ofpt, "  ");    if (protos_list[fct][0] != 'v') fprintf(ofpt, "(*pb_sp)[-1].f = ");    if (protos_list[fct][0] == 'i') fprintf(ofpt, "(MFLOAT)");    fprintf(ofpt, "%s(", function_list[fct]);    for (j = 0; j < strlen(protos_list[fct]) - 1; j++)    {      if (protos_list[fct][j+1] != 'a')      {	if (protos_list[fct][j+1] == 'c')	{					/* char */	  fprintf(ofpt, "str_buf%db", j);	}	else	{					/* MINT or MFLOAT */	  if (protos_list[fct][j+1] == 'i') fprintf(ofpt, "(MINT)");	  fprintf(ofpt, "(*pb_sp)[%d].f", j - 1);	}	if (j < strlen(protos_list[fct]) - 2) fprintf(ofpt, ", ");      }      else      {				/* variable length argument list */	fprintf(ofpt, "nargs, (MFLOAT*)(*pb_sp + %ld)",		strlen(protos_list[fct]) - 4);	break;      }    }    fprintf(ofpt, ");\n}\n\n");  }  fprintf(ofpt, "\n");    /*===== make function-pointer array =====*/  fprintf(ofpt, "/* Array of function pointers */\n");  fprintf(ofpt, "/******************************/\n\n");  fprintf(ofpt, "FUNCTION_PTR_ARR_T function_ptr_arr[] =\n{\n");  for (fct = 0; fct < nfunctions; fct++)  {    nargs = strlen(protos_list[fct]) - 1;    if (protos_list[fct][strlen(protos_list[fct])-1] == 'a')      nargs = -(nargs - 2);    fprintf(ofpt, "  {\"%s\", if_%s, %ld},\n",	    function_list[fct], function_list[fct], nargs);  }  fprintf(ofpt, "  {NULL, NULL, 0}\n};\n");    if (ferror(ofpt))  {    printf("ERROR of mknfcts: Write error on \"%s\".\n", argv[argc-2]);    error_flag = EXIT_FAILURE;  }  fclose(ofpt);  release_memory();  return error_flag;} /* end of main() */

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?