⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ic.c

📁 操作系统源代码
💻 C
字号:
/*****************************************************************//*								 *//*	ic.c							 *//*								 *//*		The main loop of the "Integer Calculator". 	 *//*								 *//*****************************************************************//*  origination          1988-Apr-6   	    Terrence W. Holm 	 *//*  added Exec_Shell()   1988-Apr-11	    Terrence W. Holm 	 *//*  added "s+"		 1988-Apr-18	    Terrence W. Holm 	 *//*  added cmd line args  1988-May-13	    Terrence W. Holm 	 *//*  'i' also does 'o'	 1988-May-28	    Terrence W. Holm 	 *//*  if ~dec:unsigned *%/ 1988-Jul-10	    Terrence W. Holm 	 *//*****************************************************************/#include <sys/types.h>#include <sys/wait.h>#include <signal.h>#include <string.h>#include <stdlib.h>#include <unistd.h>#include <stdio.h>#include "ic.h"static char copyright[] = {"ic    (c) Terrence W. Holm 1988"};/****************************************************************//*							 *//*	main()						 *//*							 *//*		Initialize. Enter the main processing loop. *//*							 *//****************************************************************/int main(argc, argv)int argc;char *argv[];{  ic_state state;		/* This state record is passed to most procs */  Init_State(&state);  state.scratch_pad = (FILE *) NULL;	/* No 'w' command yet	 */  Init_Getc(argc, argv);	/* Refs to command line args	 */  if (Init_Termcap() == 0) {	fprintf(stderr, "ic requires a termcap entry\n");	exit(1);  }  Save_Term();			/* Save terminal characteristics */  if (signal(SIGINT, SIG_IGN) != SIG_IGN) {	signal(SIGINT, Sigint);	signal(SIGQUIT, Sigint);  }  Set_Term();			/* Setup terminal characteristics */  Draw_Screen(&state);  while (1) {	int rc = Process(&state, Get_Char());	if (rc == EOF) break;	if (rc == ERROR) putchar(BELL);  }  Reset_Term();			/* Restore terminal characteristics */  exit(OK);}/****************************************************************//*							 	*//*	Init_State()					 	*//*							 	*//*		Initialize the state record.		 	*//*							 	*//****************************************************************/void Init_State(s)ic_state *s;{  s->stack[0] = 0;  s->stack_size = 1;  s->register_mask = 0x000;  s->last_tos = 0;  s->mode = LAST_WAS_ENTER;  s->input_base = DECIMAL;  s->output_base = DECIMAL;}/*****************************************************************//*								 *//*	Sigint()						 *//*								 *//*		Terminate the program on an interrupt (^C) 	 *//*		or quit (^\) signal.			 	 *//*							 	 *//*****************************************************************/void Sigint(sig)int sig;{  Reset_Term();			/* Restore terminal characteristics */  exit(1);}/*****************************************************************//*								 *//*	Process( state, input_char )				 *//*								 *//*		Determine the function requested by the  	 *//*		input character. Returns OK, EOF or ERROR. 	 *//*							 	 *//******************************************************************/int Process(s, c)ic_state *s;int c;{  switch (c) {      case '0':      case '1':      case '2':      case '3':      case '4':      case '5':      case '6':      case '7':      case '8':      case '9':	return(Enter_Numeric(s, (int) c - '0'));      case 'a':      case 'b':      case 'c':      case 'd':      case 'e':      case 'f':	return(Enter_Numeric(s, (int) c - 'a' + 10));      case 'h':      case '?':			/* Help	*/	Draw_Help_Screen();	Get_Char();	Draw_Screen(s);	return(OK);      case 'i':			/* Set i/p and o/p base	 */	{		int numeral;		Draw_Prompt("Base?");		numeral = Get_Base(Get_Char());		Erase_Prompt();		if (numeral == ERROR || numeral == ASCII) return(ERROR);		s->input_base = numeral;		s->output_base = numeral;		s->mode = LAST_WAS_FUNCTION;		Draw_Screen(s);		return(OK);	}      case 'l':      case ESC_PGDN:		/* Get last tos value */	if (s->mode != LAST_WAS_ENTER) Push(s);	s->stack[0] = s->last_tos;	s->mode = LAST_WAS_FUNCTION;	Draw_Stack(s);	return(OK);      case 'm':			/* Invoke a Minix shell */	Reset_Term();	Exec_Shell();	Set_Term();	Draw_Screen(s);	return(OK);      case 'o':			/* Set output base */	{		int numeral;		Draw_Prompt("Base?");		numeral = Get_Base(Get_Char());		Erase_Prompt();		if (numeral == ERROR) return(ERROR);		s->output_base = numeral;		s->mode = LAST_WAS_FUNCTION;		Draw_Screen(s);		return(OK);	}      case 'p':      case ESC_DOWN:		/* Pop: Roll down stack */	{		long int temp = s->stack[0];		int i;		for (i = 0; i < s->stack_size - 1; ++i)			s->stack[i] = s->stack[i + 1];		s->stack[s->stack_size - 1] = temp;		s->mode = LAST_WAS_FUNCTION;		Draw_Stack(s);		return(OK);	}      case 'q':      case ESC_END:		/* Quit		 */      case EOF:      case CTRL_D:	return(EOF);      case 'r':      case ESC_LEFT:		/* Recall from register */	{		int numeral;		Draw_Prompt("Register?");		numeral = Get_Char() - '0';		Erase_Prompt();		if (numeral < 0 || numeral >= REGISTERS ||				    ((1 << numeral) & s->register_mask) == 0)			return(ERROR);		if (s->mode != LAST_WAS_ENTER) Push(s);		s->stack[0] = s->registers[numeral];		s->mode = LAST_WAS_FUNCTION;		Draw_Stack(s);		return(OK);	}      case 's':      case ESC_RIGHT:		 /* Store in register,  */			 	 /* Or accumulate if "s+" is typed */	{		int c;		int numeral;		Draw_Prompt("Register?");		c = Get_Char();		if (c == ESC_PLUS)			c = '+';	/* Allow keypad '+' */		if (c == '+') {			Draw_Prompt("Accumulator?");			numeral = Get_Char() - '0';		} else			numeral = c - '0';		Erase_Prompt();		if (numeral < 0 || numeral >= REGISTERS) return(ERROR);		if (c != '+' || (s->register_mask & (1 << numeral)) == 0) {			s->register_mask |= 1 << numeral;			s->registers[numeral] = s->stack[0];		} else			s->registers[numeral] += s->stack[0];		s->mode = LAST_WAS_FUNCTION;		Draw_Registers(s);		return(OK);	}      case 't':			/* Translate from ASCII */	{		long int numeral;		Draw_Prompt("Character?");		numeral = (long int) Getc();		Erase_Prompt();		if (s->mode != LAST_WAS_ENTER) Push(s);		s->stack[0] = numeral;		s->mode = LAST_WAS_FUNCTION;		Draw_Stack(s);		return(OK);	}      case 'w':      case ESC_PGUP:		/* Write tos to a file */	{		if (s->scratch_pad == (FILE *) NULL) {			/* Try to open a scratch pad file  */			strcpy(s->file_name, "./pad");			if ((s->scratch_pad = fopen(s->file_name,"w")) ==NULL){				/* Unsuccessful, try in /tmp  */				char *id;				strcpy(s->file_name, "/tmp/pad_");				if ((id = cuserid(NULL)) == NULL)					return(ERROR);				strcat(s->file_name, id);				if ((s->scratch_pad = fopen(s->file_name, "w")) == NULL)					return(ERROR);			}			Draw_Screen(s);		}		/* We have a successfully opened file  */		Print_Number(s->scratch_pad, s->stack[0], s->output_base);		putc('\n', s->scratch_pad);		fflush(s->scratch_pad);		s->mode = LAST_WAS_FUNCTION;		return(OK);	}      case 'x':      case ESC_UP:		/* Exchange top of stack */	{		long int temp = s->stack[0];		if (s->stack_size < 2) return(ERROR);		s->stack[0] = s->stack[1];		s->stack[1] = temp;		s->mode = LAST_WAS_FUNCTION;		Draw_Stack(s);		return(OK);	}      case 'z':      case ESC_HOME:		/* Clear all */	Init_State(s);	Draw_Screen(s);	return(OK);      case BS:      case DEL:			/* Clear top of stack */	s->stack[0] = 0;	s->mode = LAST_WAS_ENTER;	Draw_Top_of_Stack(s);	return(OK);      case '\n':		/* Enter */	Push(s);	s->mode = LAST_WAS_ENTER;	Draw_Stack(s);	return(OK);      case '.':			/* Change sign */	s->last_tos = s->stack[0];	s->stack[0] = -s->stack[0];	s->mode = LAST_WAS_FUNCTION;	Draw_Top_of_Stack(s);	return(OK);      case '+':      case ESC_PLUS:		/* Add */	if (s->stack_size < 2) return(ERROR);	s->last_tos = s->stack[0];	Pop(s);	s->stack[0] += s->last_tos;	s->mode = LAST_WAS_FUNCTION;	Draw_Stack(s);	return(OK);      case '-':      case ESC_MINUS:		/* Subtract */	if (s->stack_size < 2) return(ERROR);	s->last_tos = s->stack[0];	Pop(s);	s->stack[0] -= s->last_tos;	s->mode = LAST_WAS_FUNCTION;	Draw_Stack(s);	return(OK);      case '*':			/* Multiply */	if (s->stack_size < 2) return(ERROR);	s->last_tos = s->stack[0];	Pop(s);	if (s->input_base == DECIMAL)		s->stack[0] *= s->last_tos;	else		s->stack[0] = (long int) (UNS(s->stack[0]) * UNS(s->last_tos));	s->mode = LAST_WAS_FUNCTION;	Draw_Stack(s);	return(OK);      case '/':			/* Divide */	if (s->stack_size < 2 || s->stack[0] == 0) return(ERROR);	s->last_tos = s->stack[0];	Pop(s);	if (s->input_base == DECIMAL)		s->stack[0] /= s->last_tos;	else		s->stack[0] = (long int) (UNS(s->stack[0]) / UNS(s->last_tos));	s->mode = LAST_WAS_FUNCTION;	Draw_Stack(s);	return(OK);      case '%':      case ESC_5:		/* Remainder */	if (s->stack_size < 2 || s->stack[0] == 0) return(ERROR);	s->last_tos = s->stack[0];	Pop(s);	if (s->input_base == DECIMAL)		s->stack[0] %= s->last_tos;	else		s->stack[0] = (long int) (UNS(s->stack[0]) % UNS(s->last_tos));	s->mode = LAST_WAS_FUNCTION;	Draw_Stack(s);	return(OK);      case '~':			/* Not */	s->last_tos = s->stack[0];	s->stack[0] = ~s->stack[0];	s->mode = LAST_WAS_FUNCTION;	Draw_Top_of_Stack(s);	return(OK);      case '&':			/* And */	if (s->stack_size < 2) return(ERROR);	s->last_tos = s->stack[0];	Pop(s);	s->stack[0] &= s->last_tos;	s->mode = LAST_WAS_FUNCTION;	Draw_Stack(s);	return(OK);      case '|':			/* Or */	if (s->stack_size < 2) return(ERROR);	s->last_tos = s->stack[0];	Pop(s);	s->stack[0] |= s->last_tos;	s->mode = LAST_WAS_FUNCTION;	Draw_Stack(s);	return(OK);      case '^':			/* Exclusive-or */	if (s->stack_size < 2) return(ERROR);	s->last_tos = s->stack[0];	Pop(s);	s->stack[0] ^= s->last_tos;	s->mode = LAST_WAS_FUNCTION;	Draw_Stack(s);	return(OK);      default:		return(ERROR);  }}/*****************************************************************//*								 *//*	Enter_Numeric( state, numeral )				 *//*								 *//*		A numeral (0 to 15) has been typed.		 *//*		If a number is currently being entered	 	 *//*		then shift it over and add this to the		 *//*		display. If the last operation was a function    *//*		then push up the stack first. If the last 	 *//*		key was "ENTER", then clear out the top of	 *//*		the stack and put the numeral there.		 *//*								 *//*		Returns OK or ERROR.				 *//*								 *//*****************************************************************/int Enter_Numeric(s, numeral)ic_state *s;int numeral;{  if (numeral >= s->input_base) return(ERROR);  switch (s->mode) {      case LAST_WAS_FUNCTION:	Push(s);	s->stack[0] = numeral;	Draw_Stack(s);	break;      case LAST_WAS_NUMERIC:	s->stack[0] = s->stack[0] * s->input_base + numeral;	Draw_Top_of_Stack(s);	break;      case LAST_WAS_ENTER:	s->stack[0] = numeral;	Draw_Top_of_Stack(s);	break;      default:	fprintf(stderr, "Internal failure (mode)\n");	Sigint(0);  }  s->mode = LAST_WAS_NUMERIC;  return(OK);}/*****************************************************************//*								 *//*	Push( state )						 *//*								 *//*		Push up the stack one level.			 *//*								 *//*****************************************************************/void Push(s)ic_state *s;{  int i;  if (s->stack_size == STACK_SIZE) --s->stack_size;  for (i = s->stack_size; i > 0; --i) s->stack[i] = s->stack[i - 1];  ++s->stack_size;}/*****************************************************************//*								 *//*	Pop( state )						 *//*								 *//*		Pop the stack down one level.			 *//*		This routine is only called with 		 *//*		the stack size > 1.				 *//*								 *//*****************************************************************/void Pop(s)ic_state *s;{  int i;  for (i = 0; i < s->stack_size - 1; ++i) s->stack[i] = s->stack[i + 1];  --s->stack_size;}/****************************************************************//*							  	*//*	Exec_Shell()					  	*//*							  	*//*		Fork off a sub-process to exec() the shell.  	*//*							  	*//****************************************************************/void Exec_Shell(){  int pid = fork();  if (pid == -1) return;  if (pid == 0) {	/* The child process  */	extern char **environ;	char *shell = getenv("SHELL");	if (shell == NULL) shell = "/bin/sh";	execle(shell, shell, (char *) 0, environ);	perror(shell);	exit(127);  }  /* The parent process: ignore signals, wait for sub-process	 */  signal(SIGINT, SIG_IGN);  signal(SIGQUIT, SIG_IGN);  {	int status;	int w;	while ((w = wait(&status)) != pid && w != -1);  }  signal(SIGINT, Sigint);  signal(SIGQUIT, Sigint);  return;}

⌨️ 快捷键说明

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