📄 basic.c
字号:
/****************************************************************//* *//* Name: basic.c *//* *//* Project: NeuroBasic, basic package *//* *//* Survey: This is a simple Basic b-code compiler which *//* can be used as a comfortable command shell for *//* any program. The actual compiler is found in *//* compiler.c. *//* The functions m_fctptr() and user_server() *//* build an interface to any user application and *//* are expected to be external. *//* *//* Author: Urs Mueller *//* Electronics Laboratory, ETH Zuerich *//* Switzerland *//* *//* Created: September 5, 1992 *//* Modified: November 15, 1996 (bf) *//* *//****************************************************************/#include <stdio.h>#include <stdlib.h>#include <string.h>#include <ctype.h>#include <setjmp.h>#include <math.h>#include <signal.h>#include <m_host.h>#include "basic.h"#include "allhfcts.h"/* stuff for simple sim *//************************/#ifdef __MUSIC__#define setjmp(env) 0#define longjmp(env, val)#endiftypedef struct{long a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z;long A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z;} fil_t;typedef struct{long ft_a, ft_b;fil_t a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z;fil_t A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z;fil_t a1,b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1,m1,n1,o1,p1,q1,r1,s1,t1, u1,v1,x1,y1,z1;fil_t a2,b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2,m2,n2,o2,p2,q2,r2,s2,t2, u2,v2,x2,y2,z2;} fill_t; /* used to create local workspace */extern jmp_buf env_host, env_pe;/* global variables *//********************/long prg_line; /* program line */static MINT l; /* program-line counter */static MINT lpos = 0; /* listing position */static MINT i;char str_buf[STR_BUF_MAX]; /* string buffer */static UMINT mstr_buf[STR_BUF_MAX]; /* to send strings to Music */long nfunctions; /* number of basic functions */char cmdbuf[CMD_MAX+1]; /* command-line buffer */char *bsrc[PRG_MAX]; /* array of program-line pointers */static FILE *fpt; /* file pointer */static FILE *out_fpt; /* file pointer output file */static int term_signal = FALSE; /* to abort with ctrl-c */static int turn_byte_flag;MFCT_TAB_T mfct_tab;static void handle_sigint(int sigtype)/*==================================*/{ term_signal = TRUE; signal(SIGINT, SIG_DFL); /* a second ctrl-c kills Basic */} /* end of handle_sigint() */void turn_byte_order(MINT *ptr, MINT nwords)/*========================================*/{ union { MINT mint; PACKED_CHARS_T pack; } tr1, tr2; for (i = 0; i < nwords; i++) { tr1.mint = *ptr; tr2.pack.char0 = tr1.pack.char3; tr2.pack.char1 = tr1.pack.char2; tr2.pack.char2 = tr1.pack.char1; tr2.pack.char3 = tr1.pack.char0; *ptr++ = tr2.mint; }} /* end of turn_byte_order() */static char *skipws(char *s)/*========================*//* returns the first location in string "s" that contains no white space*/{ while (isspace(*s)) s++; return s;} /* end of skipws() */static void call_m_get_fct_ptrs(void)/*=================================*/{ fill_t stack; /* remaining stack for lifetime.. */ /* ..of MUSIC task */ stack.ft_a = 1; /* to make sure variable is.. */ stack.ft_b = stack.ft_a; /* ..allocated */ if (setjmp(env_host) == 0) { MCALL(m_get_fct_ptrs()); longjmp(env_host, 1); }} /* end of call_m_fctptr() */static void load_function_table(void)/*=================================*/{ message_t msg; MINT *plabel; mfct_tab.mft_func_ptr = NULL; mfct_tab.mft_nargs = NULL; mfct_tab.mft_fct_names = NULL; mfct_tab.mft_nitems = 0; call_m_get_fct_ptrs(); Rd_from_music(msg, sizeof(msg)); if (msg[0].i > 0) { mfct_tab.mft_func_ptr = (MINT*)malloc(msg[1].i * sizeof(MINT)); if (mfct_tab.mft_func_ptr == NULL) { printf("Not enough memory on host side to run program!\n"); return; } mfct_tab.mft_nargs = (MINT*)(mfct_tab.mft_func_ptr + msg[0].i); plabel = mfct_tab.mft_nargs + msg[0].i; mfct_tab.mft_fct_names = plabel + 1; mfct_tab.mft_nitems = msg[0].i; Rd_from_music(mfct_tab.mft_func_ptr, (MINT)(msg[1].i * sizeof(MINT))); if (*(char*)plabel != 0x12) { turn_byte_order(mfct_tab.mft_fct_names, msg[1].i - msg[0].i * 2 - 1); turn_byte_flag = TRUE; } else { turn_byte_flag = FALSE; } } else if (msg[1].i < 0) printf("Not enough memory on processor array side.\n");} /* end of load_function_table() */static void release_function_table(void)/*====================================*/{ if (mfct_tab.mft_func_ptr != NULL) free(mfct_tab.mft_func_ptr); mfct_tab.mft_func_ptr = NULL; mfct_tab.mft_nargs = NULL; mfct_tab.mft_fct_names = NULL; mfct_tab.mft_nitems = 0;} /* end of release_function_table() */static void handle_error_code(MINT b_pos, MINT fptr)/*================================================*/{ const char *fct_name; MINT *emsg, src_line; size_t i, k; message_t msg; /*=== find name of function that reports error ===*/ fct_name = "unknown"; for (i = 0; i < mfct_tab.mft_nitems; i++) { if (mfct_tab.mft_func_ptr[i] == fptr) { fct_name = (char*)mfct_tab.mft_fct_names; for (k = 0; k < i; k++) fct_name += strlen(fct_name) + 1; break; } } printf(INDENT); printf("ERROR in function \"%s()\"", fct_name); src_line = bc_srcline(b_pos); if (src_line >= 0) printf(" on line %ld", src_line); printf(":\n"); Rd_from_music(msg, sizeof(msg)); emsg = (MINT*)malloc(msg[0].i * sizeof(MINT)); Rd_from_music(emsg, (MINT)(msg[0].i * sizeof(MINT))); if (turn_byte_flag) turn_byte_order(emsg, msg[0].i); printf(INDENT); printf("%s\n", (char*)emsg); free(emsg);} /* end of handle_error_code() */static int do_print(int *pnew_line, MINT b_pos)/*===========================================*//* reads and prints out the printer queue */{ MINT prn_pos; printq_t prn_msg; double x; const char *p; Rd_from_music(prn_msg, sizeof(prn_msg)); prn_pos = 1; while (prn_msg[prn_pos].i != C_END) { switch ((int)(prn_msg[prn_pos++].i)) { case C_PRINTNL: fprintf(out_fpt,"\n"); *pnew_line = TRUE; break; case C_PRINTTAB: if (*pnew_line && out_fpt == stdout) fprintf(out_fpt,INDENT); fprintf(out_fpt,"\t"); *pnew_line = FALSE; break; case C_PRINTS: p = bc_str_get(prn_msg[prn_pos++].i, b_pos, &term_signal); if (term_signal) break; if (*pnew_line && out_fpt == stdout) fprintf(out_fpt,INDENT); fprintf(out_fpt, "%s", p); fflush(out_fpt); *pnew_line = FALSE; break; case C_PRINTF: /*** HACK BY BF ***/ /* printf("C_PRINTF\n"); */ if (*pnew_line && out_fpt == stdout) fprintf(out_fpt,INDENT); if (floor(prn_msg[prn_pos].f) == prn_msg[prn_pos].f) fprintf(out_fpt,"%ld", (long)prn_msg[prn_pos].f); else { x = log10(fabs(prn_msg[prn_pos].f)); if (x > 4.0 || x < -4.0) fprintf(out_fpt,"%.6e", (float)prn_msg[prn_pos].f); else fprintf(out_fpt,"%.6f", (float)prn_msg[prn_pos].f); } prn_pos++; fflush(out_fpt); *pnew_line = FALSE; break; case C_OPENFILE: /*** HACK BY BF ***/ /* printf("C_OPENFILE\n"); */ p = bc_str_get(prn_msg[prn_pos++].i, b_pos, &term_signal); if (term_signal) break; out_fpt = fopen(p, "a"); if (out_fpt == NULL) { printf(INDENT); printf("Cannot open file \"%s\".\n", p); out_fpt = stdout; } *pnew_line = TRUE; break; case C_CLOSEFILE: /*** HACK BY BF ***/ /* printf("C_CLOSEFILE\n"); */ if (out_fpt != stdout) fclose(out_fpt); out_fpt = stdout; *pnew_line = TRUE; break; } /* end of switch */ } /* end of while */ return term_signal;} /* end of do_print() */static void b_server(void)/*======================*/{ message_t msg; size_t i; int new_line = TRUE; char *pstr; double x; const char *p; signal(SIGINT, handle_sigint); do { Rd_from_music(msg, sizeof(msg)); switch ((int)msg[0].i) { case C_USER_FCT: /* user function */ if (msg[1].i >= 0 && msg[1].i < HOST_FCT_MAX) host_fcts[msg[1].i](msg); else { printf(INDENT); printf("Call to unknown user server function: %ld.\n", msg[1].i); } break; case C_PRINT: term_signal |= do_print(&new_line, msg[3].i); msg[0].i = term_signal; /* basic program can be.. */ term_signal = FALSE; /* ..terminated here by user */ Wr_to_music(msg, sizeof(msg)); break; case C_INPUT: if (new_line) printf(INDENT); printf("? "); fflush(stdout); fgets(cmdbuf, CMD_MAX, stdin); msg[0].f = (MFLOAT)atof(cmdbuf); Wr_to_music(msg, sizeof(msg)); new_line = TRUE; break; case C_ASSIGN_STR: bc_str_dup(msg[2].i, msg[1].i, msg[3].i, &term_signal); msg[1].i = term_signal; Wr_to_music(msg, sizeof(msg)); break; case C_STR_ADD: /* concat. two strings */ msg[1].f = (MFLOAT)bc_str_add(msg[1].i, msg[2].i, msg[3].i, &term_signal); msg[3].i = term_signal; Wr_to_music(msg, sizeof(msg)); /* New string pointer */ break; case C_STR_STR: if (floor(msg[1].f) == msg[1].f) /* integer */ { sprintf(str_buf,"%ld", (long)msg[1].f); } else { x = log10(fabs(msg[1].f)); if (x > 4.0) sprintf(str_buf,"%.6e", (float)msg[1].f); else sprintf(str_buf,"%.6f", (float)msg[1].f); } msg[1].i = bc_str_new(str_buf, msg[3].i, &term_signal); Wr_to_music(msg, sizeof(msg)); break; case C_STR_DEL_STACK: /* delete temporay string stack */ bc_str_delstack(); break; case C_SENDSTRING: pstr = bc_str_get(msg[1].i, -1, &term_signal); for (i = 0; pstr && *pstr && i < STR_BUF_MAX-1; i++) mstr_buf[i] = (UMINT)(*pstr++); mstr_buf[i] = 0; Wr_to_music(mstr_buf, sizeof(mstr_buf)); break; case C_FNERROR: if (!new_line) printf("\n"); handle_error_code(msg[2].i, msg[3].i); break; case C_VARERROR: if (!new_line) printf("\n"); bc_print_varerror(msg[2].i, msg[3].i); break; case C_ERR_ARRAY: bc_print_error(2, msg[1].i, 0, msg[3].i);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -