#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<netdb.h>
#include<stdio.h>
#include<ctype.h>
#include<string.h>
#define MAXLINE 4096
#define MAX 100
/*The Server Port Number*/
#define PORT 4600
/* calculator global variables *
*******************************/
/*Where the values of the numbers scanned
are stored*/
double number[MAX];
/*The postfix code generated in the prasing
phase*/
char postfix_code[MAX];
/*The position of Scanned in the Expression*/
int position=0;
/*The number of numbers scanned*/
/*The number of code Generated*/
int num,code_counter=0;
char character;
/*The position of each number scanned in
number[](above)*/
int numberindex;
/*The Code Generated for each number
Scanned*/
char NUMERIC = 'N';
/*The Result after Evaluating The Code*/
int result;
/*Prints a message when an error occurs and
exits*/
void error(char*);
void parse(void);
void addCode(char);
void scanNumber(void);
void arithmeticLevel1();
void arithmeticLevel2();
void scanAndParse();
void getIdentifier();
int evaluate();
void calculator();
/* server global variables *
****************************/
/*The struct in which the result will be
strored*/
struct{
int result;
}reply;
/*The function(Expression) length*/
int
fun_length;
/*The Expression(function) that is received
from the Client*/
char recvline[MAXLINE+1];
char function[MAXLINE+1];
int main(){
/*the Socket for Listenning to the
connection requests comming from
Clients*/
int sock_listen;
/*The Socket used for Connecting to a
Client*/
int sock_service;
/*The length of the struct sockaddr for a
Client*/
int client_length;
/*the stucture for the address (Clients,
Server)*/
struct sockaddr_in client,server;
/*Create the socket listen */
/*Verify if it is created ==>
(sock_listen>0) else print a message and exit*/
if((sock_listen = socket(AF_INET,
SOCK_STREAM, 0))<0)
error("can not create the
soket");
/*allocate the space for the Server struct
address*/
bzero(&server,sizeof(server));
/*Fill the Server struct address*/
server.sin_family = AF_INET;
server.sin_port = htons(PORT);
/*This sever is in the localhost*/
server.sin_addr.s_addr = INADDR_ANY;
/*Bind The Socket listen*/
/*Verify the Bind ==> the value returned
by bind = 0 */
if(bind(sock_listen, (struct
sockaddr*)&server, sizeof(server))!=0)
error("can not bind the socket");
/*To allow up to 5 requests*/
listen(sock_listen,5);
while(1){
client_length= sizeof(client);
/*Create the Socket Service after accepting the Connection*/
sock_service = accept(sock_listen, (struct sockaddr*) & client,
&client_length);
/* this is for creating processes that will handle different requests
* from different clients at the same time*/
if(fork() == 0){
/*close the socket listen*/
close(sock_listen);
/*Allocating space for the received expression*/
bzero((char*)&recvline, sizeof(recvline));
/*Receining the Expression and putting it into recvline*/
recv(sock_service, (char*)&recvline, sizeof(recvline),0);
/*Allocating Space for the Reply*/
bzero((char*)&reply, sizeof(reply));
strcpy(function,recvline);
fun_length = strlen(function);
/*Having the expression(function) we calculate the result*/
calculator();
/*Store the Result*/
reply.result = result;
postfix_code[0] = '\0';
/*re_initialize
some of the Global Variables related to calculation*/
code_counter=0;
numberindex=0;
/*Sending The reply to the Client*/
send(sock_service, (char*)&reply, sizeof(reply),0);
exit(0);
}
/*Closing the Connection to the Client*/
close(sock_service);
}
}
void error (char* str){
printf("%s",str);
exit(1);
}
/*
It parses the function (expression) using other functions that we have
*
below and following a specific Grammar it Generates the Code, then
*
Evalutes it*/
void calculator(){
parse();
result = evaluate();
}
void parse() {
char c;
int counter =0;
num = 0;
position = 0;
function[fun_length]= ')';
scanAndParse();
}
/* Appends postfix code to compiled code. *
* *
* the parameters: code. *
* return: none. *
* */
void addCode(char code) {
postfix_code[code_counter] =
code;
code_counter ++;
}
/* Scans a number. *
* *
* the parameters: none.
*
* return: none.
*
* */
void scanNumber() {
int value =0;
int numlen=0;
char numstr[MAX];
do {
numstr[numlen] = function[position];
position++;
numlen++;
}
while(isdigit(function[position]));
value = atoi(numstr);
number[num++] = value;
addCode(NUMERIC);
}
/* Gets an identifier starting from current parsing pointer*
*
*
* the parameters: code. *
* return: none. *
* */
void getIdentifier() {
position++;
if(isdigit(function[position]))
scanNumber();
else if( function[position] == '(') {
scanAndParse();
position++;
}
}
/* Scans Multiplications and divisions *
* *
* the parameters: none.
*
* return: none. *
* */
void arithmeticLevel2() {
char operat = function[position];
do {
getIdentifier();
addCode(operat);
} while ((character == '*')||(character ==
'/'));
}
/* Scans Additions and Subtractions.
*
* *
* the parameters: none.
*
* return: none.
*
* */
void arithmeticLevel1() {
char operat = function[position];
do{
getIdentifier();
if((character == '*')||(character == '/'))
arithmeticLevel2();
addCode(operat);
} while ((character == '+')||(character ==
'-'));
}
/* Scans And Parse. *
* *
* the parameters: code. *
* return: result. *
* */
void scanAndParse() {
getIdentifier();
do {
switch (function[position]) {
case '+':
case '-': arithmeticLevel1(); break;
case '*':
case '/': arithmeticLevel2(); break;
case ')': return;
}
} while(1);
}
/* Evaluate the Code and returns the result. *
* *
* the parameters: code. *
* return: none. *
* */
int evaluate() {
int stack_pointer = -1;
int code_pointer = 0;
char code;
int stack[MAX];
int code_length;
code_length = strlen(postfix_code);
while(code_pointer<code_length) {
code
= postfix_code[code_pointer];
switch(code) {
case '+' : stack[stack_pointer-1] +=
stack[stack_pointer];
stack_pointer--; break;
case '-' : stack[stack_pointer-1] -=
stack[stack_pointer];
stack_pointer--; break;
case '*' : stack[stack_pointer-1] *=
stack[stack_pointer];
stack_pointer--; break;
case '/' : stack[stack_pointer-1] /=
stack[stack_pointer];
stack_pointer--; break;
case 'N' : stack[++stack_pointer] =
number[numberindex++];
break;
}
code_pointer++;
}
return stack[0];
}