| /* |
| *Copyright(c)2004,Cisco URP imburses and Network Information Center in Beijing University of Posts and Telecommunications researches. |
| * |
| *All right reserved |
| * |
| *File Name: expValueTable.c |
| *File Description: expValueTable MIB operation. |
| * |
| *Current Version:1.0 |
| *Author:JianShun Tong |
| *Date:2004.8.20 |
| */ |
| |
| |
| /* |
| * This file was generated by mib2c and is intended for use as |
| * a mib module for the ucd-snmp snmpd agent. |
| */ |
| |
| |
| /* |
| * This should always be included first before anything else |
| */ |
| #include <net-snmp/net-snmp-config.h> |
| #if HAVE_STDLIB_H |
| #include <stdlib.h> |
| #endif |
| |
| #include <stdio.h> |
| |
| #if HAVE_STRING_H |
| #include <string.h> |
| #else |
| #include <strings.h> |
| #endif |
| #ifdef HAVE_LIMITS_H |
| #include <limits.h> |
| #endif |
| |
| |
| /* |
| * minimal include directives |
| */ |
| #include <net-snmp/net-snmp-includes.h> |
| #include <net-snmp/agent/net-snmp-agent-includes.h> |
| #include "header_complex.h" |
| #include "expExpressionTable.h" |
| #include "expValueTable.h" |
| #include "expObjectTable.h" |
| |
| |
| /* |
| * expValueTable_variables_oid: |
| * this is the top level oid that we want to register under. This |
| * is essentially a prefix, with the suffix appearing in the |
| * variable below. |
| */ |
| |
| oid expValueTable_variables_oid[] = |
| { 1, 3, 6, 1, 2, 1, 90, 1, 3, 1 }; |
| |
| struct s_node { |
| unsigned data; |
| struct s_node *next; |
| }; |
| typedef struct s_node nodelink; |
| nodelink *operater = NULL; |
| nodelink *operand = NULL; |
| |
| /* |
| * variable2 expObjectTable_variables: |
| */ |
| |
| struct variable2 expValueTable_variables[] = { |
| /* |
| * magic number , variable type , ro/rw , callback fn , L, oidsuffix |
| */ |
| #define EXPVALUECOUNTER32VAL 2 |
| {EXPVALUECOUNTER32VAL, ASN_COUNTER, NETSNMP_OLDAPI_RONLY, |
| var_expValueTable, 2, {1, 2}}, |
| #define EXPVALUEUNSIGNED32VAL 3 |
| {EXPVALUEUNSIGNED32VAL, ASN_UNSIGNED, NETSNMP_OLDAPI_RONLY, |
| var_expValueTable, 2, {1, 3}}, |
| #define EXPVALUETIMETICKSVAL 4 |
| {EXPVALUETIMETICKSVAL, ASN_UNSIGNED, NETSNMP_OLDAPI_RONLY, |
| var_expValueTable, 2, {1, 4}}, |
| #define EXPVALUEINTEGER32VAL 5 |
| {EXPVALUEINTEGER32VAL, ASN_INTEGER, NETSNMP_OLDAPI_RONLY, |
| var_expValueTable, 2, {1, 5}}, |
| #define EXPVALUEIPADDRESSVAL 6 |
| {EXPVALUEIPADDRESSVAL, ASN_IPADDRESS, NETSNMP_OLDAPI_RONLY, |
| var_expValueTable, 2, {1, 6}}, |
| #define EXPVALUEOCTETSTRINGVAL 7 |
| {EXPVALUEOCTETSTRINGVAL, ASN_OCTET_STR, NETSNMP_OLDAPI_RONLY, |
| var_expValueTable, 2, {1, 7}}, |
| #define EXPVALUEOIDVAL 8 |
| {EXPVALUEOIDVAL, ASN_OBJECT_ID, NETSNMP_OLDAPI_RONLY, |
| var_expValueTable, 2, {1, 8}}, |
| #define EXPVALUECOUNTER64VAL 9 |
| {EXPVALUECOUNTER64VAL, ASN_INTEGER, NETSNMP_OLDAPI_RONLY, |
| var_expValueTable, 2, {1, 9}} |
| }; |
| |
| |
| /* |
| * global storage of our data, saved in and configured by header_complex() |
| */ |
| extern struct header_complex_index *expExpressionTableStorage; |
| extern struct header_complex_index *expObjectTableStorage; |
| struct header_complex_index *expValueTableStorage = NULL; |
| struct snmp_session session; |
| |
| /* |
| * init_expValueTable(): |
| * Initialization routine. This is called when the agent starts up. |
| * At a minimum, registration of your variables should take place here. |
| */ |
| void |
| init_expValueTable(void) |
| { |
| DEBUGMSGTL(("expValueTable", "initializing... ")); |
| |
| |
| /* |
| * register ourselves with the agent to handle our mib tree |
| */ |
| REGISTER_MIB("expValueTable", |
| expValueTable_variables, variable2, |
| expValueTable_variables_oid); |
| init_snmp("snmpapp"); |
| |
| /* |
| * Initialize a "session" that defines who we're going to talk to |
| */ |
| snmp_sess_init(&session); /* set up defaults */ |
| session.peername = strdup("localhost"); |
| |
| DEBUGMSGTL(("expValueTable", "done.\n")); |
| } |
| |
| struct expValueTable_data * |
| create_expValueTable_data(void) |
| { |
| struct expValueTable_data *StorageNew; |
| |
| StorageNew = SNMP_MALLOC_STRUCT(expValueTable_data); |
| |
| /* |
| * fill in default row values here into StorageNew |
| */ |
| /* |
| * fill in values for all tables (even if not |
| * appropriate), since its easier to do here than anywhere |
| * else |
| */ |
| StorageNew->expExpressionOwner = strdup(""); |
| StorageNew->expExpressionName = strdup(""); |
| StorageNew->expValueInstance = calloc(1, sizeof(oid) * sizeof(2)); /* 0.0.0 */ |
| StorageNew->expValueInstanceLen = 3; |
| return StorageNew; |
| } |
| |
| /* |
| * mteTriggerTable_add(): adds a structure node to our data set |
| */ |
| int |
| expValueTable_add(struct expExpressionTable_data *expression_data, |
| char *owner, size_t owner_len, char *name, |
| size_t name_len, oid * index, size_t index_len) |
| { |
| netsnmp_variable_list *vars = NULL; |
| struct expValueTable_data *thedata, *StorageTmp; |
| struct header_complex_index *hcindex; |
| int founded = 0; |
| thedata = create_expValueTable_data(); |
| thedata->expValueCounter32Val = 0; |
| thedata->expExpressionOwner = owner; |
| thedata->expExpressionOwnerLen = owner_len; |
| thedata->expExpressionName = name; |
| thedata->expExpressionNameLen = name_len; |
| thedata->expValueInstance = index; |
| thedata->expValueInstanceLen = index_len; |
| thedata->expression_data = expression_data; |
| DEBUGMSGTL(("expValueTable", "adding data... ")); |
| /* |
| * add the index variables to the varbind list, which is |
| * used by header_complex to index the data |
| */ |
| |
| |
| snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR, (char *) thedata->expExpressionOwner, thedata->expExpressionOwnerLen); /* expExpressionOwner */ |
| snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR, (char *) thedata->expExpressionName, thedata->expExpressionNameLen); /* expExpressionName */ |
| snmp_varlist_add_variable(&vars, NULL, 0, ASN_PRIV_IMPLIED_OBJECT_ID, |
| (u_char *) thedata->expValueInstance, |
| thedata->expValueInstanceLen * sizeof(oid)); |
| |
| for (hcindex = expValueTableStorage; hcindex != NULL; |
| hcindex = hcindex->next) { |
| StorageTmp = (struct expValueTable_data *) hcindex->data; |
| if (!strcmp |
| (StorageTmp->expExpressionOwner, thedata->expExpressionOwner) |
| && (StorageTmp->expExpressionOwnerLen == |
| thedata->expExpressionOwnerLen) |
| && !strcmp(StorageTmp->expExpressionName, |
| thedata->expExpressionName) |
| && (StorageTmp->expExpressionNameLen == |
| thedata->expExpressionNameLen) |
| && !snmp_oid_compare(StorageTmp->expValueInstance, |
| StorageTmp->expValueInstanceLen, |
| thedata->expValueInstance, |
| thedata->expValueInstanceLen)) { |
| founded = 1; |
| break; |
| } |
| |
| } |
| if (!founded) { |
| header_complex_add_data(&expValueTableStorage, vars, thedata); |
| DEBUGMSGTL(("expValueTable", "registered an entry\n")); |
| } else { |
| SNMP_FREE(thedata); |
| DEBUGMSGTL(("expValueTable", |
| "already have an entry, dont registe\n")); |
| } |
| |
| |
| DEBUGMSGTL(("expValueTable", "done.\n")); |
| return SNMPERR_SUCCESS; |
| } |
| |
| |
| |
| |
| |
| unsigned long |
| Evaluate_Expression(struct expValueTable_data *vtable_data) |
| { |
| |
| struct header_complex_index *hcindex; |
| struct expObjectTable_data *objstorage, *objfound; |
| struct expValueTable_data *valstorage; |
| valstorage = vtable_data; |
| |
| char *expression; |
| char *result, *resultbak; |
| char *temp, *tempbak; |
| char intchar[10]; |
| int i = 0, j, k, l; |
| long value; |
| unsigned long result_u_long; |
| temp = malloc(100); |
| result = malloc(100); |
| tempbak = temp; |
| memset(result, 0, 100); |
| *result = '\0'; |
| resultbak = result; |
| |
| expression = vtable_data->expression_data->expExpression; |
| |
| while (*expression != '\0') { |
| if (*expression == '$') { |
| objfound = NULL; |
| i++; |
| for (j = 1; j < 100; j++) { |
| if ((*(expression + j) == '+') || |
| (*(expression + j) == '-') || |
| (*(expression + j) == '*') || |
| (*(expression + j) == '/') || |
| (*(expression + j) == '(') || |
| (*(expression + j) == ')') || |
| *(expression + j) == '\0') { |
| break; |
| } |
| } |
| sprintf(temp, "%.*s", j - 1, expression + 1); |
| l = atoi(temp); |
| expression = expression + j; |
| /* |
| * here use snmpget to get value |
| */ |
| for (hcindex = expObjectTableStorage; hcindex != NULL; |
| hcindex = hcindex->next) { |
| objstorage = (struct expObjectTable_data *) hcindex->data; |
| if (!strcmp |
| (objstorage->expExpressionOwner, |
| valstorage->expExpressionOwner) |
| && (objstorage->expExpressionOwnerLen == |
| valstorage->expExpressionOwnerLen) |
| && !strcmp(objstorage->expExpressionName, |
| valstorage->expExpressionName) |
| && (objstorage->expExpressionNameLen == |
| valstorage->expExpressionNameLen) |
| && (l == objstorage->expObjectIndex)) { |
| objfound = objstorage; |
| break; |
| } |
| } |
| |
| |
| if (!objfound) { |
| /* have err */ |
| return 0; |
| } |
| struct snmp_session *ss; |
| struct snmp_pdu *pdu; |
| struct snmp_pdu *response; |
| |
| oid anOID[MAX_OID_LEN]; |
| size_t anOID_len; |
| |
| memcpy(anOID, objfound->expObjectID, |
| objfound->expObjectIDLen * sizeof(oid)); |
| anOID_len = objfound->expObjectIDLen; |
| if (objfound->expObjectIDWildcard == EXPOBJCETIDWILDCARD_TRUE) { |
| anOID_len = |
| anOID_len + valstorage->expValueInstanceLen - 2; |
| memcpy(anOID + objfound->expObjectIDLen, |
| valstorage->expValueInstance + 2, |
| (valstorage->expValueInstanceLen - |
| 2) * sizeof(oid)); |
| } |
| struct variable_list *vars; |
| int status; |
| |
| /* |
| * Initialize the SNMP library |
| */ |
| |
| /* |
| * Initialize a "session" that defines who we're going to talk to |
| */ |
| session.version = vtable_data->expression_data->pdu_version; |
| |
| /* |
| * set the SNMPv1 community name used for authentication |
| */ |
| session.community = |
| vtable_data->expression_data->pdu_community; |
| session.community_len = |
| vtable_data->expression_data->pdu_community_len; |
| /* |
| * Open the session |
| */ |
| SOCK_STARTUP; |
| ss = snmp_open(&session); /* establish the session */ |
| |
| if (!ss) { |
| /* err */ |
| exit(2); |
| } |
| pdu = snmp_pdu_create(SNMP_MSG_GET); |
| snmp_add_null_var(pdu, anOID, anOID_len); |
| |
| /* |
| * Send the Request out. |
| */ |
| status = snmp_synch_response(ss, pdu, &response); |
| |
| /* |
| * Process the response. |
| */ |
| if (status == STAT_SUCCESS |
| && response->errstat == SNMP_ERR_NOERROR) { |
| /* |
| * SUCCESS: Print the result variables |
| */ |
| |
| vars = response->variables; |
| value = *(vars->val.integer); |
| sprintf(intchar, "%lu", value); |
| for (k = 1; k <= strlen(intchar); k++) { |
| *result = intchar[k - 1]; |
| result++; |
| } |
| |
| } else { |
| /* |
| * FAILURE: print what went wrong! |
| */ |
| |
| if (status == STAT_SUCCESS) |
| fprintf(stderr, "Error in packet\nReason: %s\n", |
| snmp_errstring(response->errstat)); |
| else |
| snmp_sess_perror("snmpget", ss); |
| |
| } |
| |
| /* |
| * Clean up: |
| * 1) free the response. |
| * 2) close the session. |
| */ |
| if (response) |
| snmp_free_pdu(response); |
| snmp_close(ss); |
| |
| SOCK_CLEANUP; |
| |
| } else { |
| *result = *expression; |
| result++; |
| expression++; |
| } |
| } |
| result_u_long = get_result(resultbak); |
| free(tempbak); |
| free(resultbak); |
| return result_u_long; |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| void |
| expValueTable_clean(void *data) |
| { |
| struct expValueTable_data *cleanme = |
| (struct expValueTable_data *) data; |
| SNMP_FREE(cleanme->expValueInstance); |
| SNMP_FREE(cleanme->expValueIpAddressVal); |
| SNMP_FREE(cleanme->expValueOctetStringVal); |
| SNMP_FREE(cleanme->expValueOidVal); |
| SNMP_FREE(cleanme); |
| } |
| |
| |
| |
| void |
| build_valuetable(void) |
| { |
| struct expExpressionTable_data *expstorage; |
| struct expObjectTable_data *objstorage, *objfound = NULL; |
| struct header_complex_index *hcindex, *object_hcindex; |
| char *expression; |
| oid *index; |
| int i = 0, j, l; |
| |
| DEBUGMSGTL(("expValueTable", "building valuetable... \n")); |
| |
| for (hcindex = expExpressionTableStorage; hcindex != NULL; |
| hcindex = hcindex->next) { |
| expstorage = (struct expExpressionTable_data *) hcindex->data; |
| if (expstorage->expExpressionEntryStatus == RS_ACTIVE) { |
| expression = expstorage->expExpression; |
| while (*expression != '\0') { |
| if (*expression == '$') { |
| i++; |
| for (j = 1; j < 100; j++) { |
| if ((*(expression + j) == '+') || |
| (*(expression + j) == '-') || |
| (*(expression + j) == '*') || |
| (*(expression + j) == '/') || |
| (*(expression + j) == '(') || |
| (*(expression + j) == ')') || |
| *(expression + j) == '\0') { |
| break; |
| } |
| } |
| { |
| char temp[100]; |
| |
| sprintf(temp, "%.*s", j - 1, expression + 1); |
| l = atoi(temp); |
| } |
| for (object_hcindex = expObjectTableStorage; |
| object_hcindex != NULL; |
| object_hcindex = object_hcindex->next) { |
| objstorage = |
| (struct expObjectTable_data *) object_hcindex-> |
| data; |
| if (!strcmp |
| (objstorage->expExpressionOwner, |
| expstorage->expExpressionOwner) |
| && (objstorage->expExpressionOwnerLen == |
| expstorage->expExpressionOwnerLen) |
| && !strcmp(objstorage->expExpressionName, |
| expstorage->expExpressionName) |
| && (objstorage->expExpressionNameLen == |
| expstorage->expExpressionNameLen) |
| && (l == objstorage->expObjectIndex)) { |
| if (objfound == NULL) { |
| objfound = objstorage; |
| } |
| if (objstorage->expObjectIDWildcard == |
| EXPOBJCETIDWILDCARD_TRUE) |
| objfound = objstorage; |
| } |
| } |
| expression = expression + j; |
| } else { |
| expression++; |
| } |
| }; |
| } |
| |
| if (!objfound) { |
| continue; |
| } |
| if (objfound->expObjectIDWildcard == EXPOBJCETIDWILDCARD_FALSE) { |
| index = calloc(1, MAX_OID_LEN); |
| *index = 0; |
| *(index + 1) = 0; |
| *(index + 2) = 0; |
| expValueTable_add(expstorage, objfound->expExpressionOwner, |
| objfound->expExpressionOwnerLen, |
| objfound->expExpressionName, |
| objfound->expExpressionNameLen, index, 3); |
| } else { |
| oid *targetOID; |
| size_t taggetOID_len; |
| targetOID = objfound->expObjectID; |
| struct snmp_pdu *pdu; |
| struct snmp_pdu *response; |
| oid *next_OID; |
| size_t next_OID_len; |
| taggetOID_len = objfound->expObjectIDLen; |
| int status; |
| struct snmp_session *ss; |
| /* |
| * Initialize the SNMP library |
| */ |
| |
| |
| /* |
| * set the SNMP version number |
| */ |
| session.version = expstorage->pdu_version; |
| |
| /* |
| * set the SNMPv1 community name used for authentication |
| */ |
| session.community = expstorage->pdu_community; |
| session.community_len = expstorage->pdu_community_len; |
| |
| /* |
| * Open the session |
| */ |
| SOCK_STARTUP; |
| ss = snmp_open(&session); /* establish the session */ |
| if (!ss) { |
| snmp_perror("ack"); |
| snmp_log(LOG_ERR, "something horrible happened!!!\n"); |
| exit(2); |
| } |
| |
| next_OID = targetOID; |
| next_OID_len = taggetOID_len; |
| do { |
| index = calloc(1, MAX_OID_LEN); |
| pdu = snmp_pdu_create(SNMP_MSG_GETNEXT); |
| |
| snmp_add_null_var(pdu, next_OID, next_OID_len); |
| |
| /* |
| * Send the Request out. |
| */ |
| status = snmp_synch_response(ss, pdu, &response); |
| |
| /* |
| * Process the response. |
| */ |
| if (status == STAT_SUCCESS |
| && response->errstat == SNMP_ERR_NOERROR) { |
| /* |
| * SUCCESS: Print the result variables |
| */ |
| |
| if (((response->variables->type >= SNMP_NOSUCHOBJECT && |
| response->variables->type <= SNMP_ENDOFMIBVIEW) |
| || snmp_oid_compare(targetOID, taggetOID_len, |
| response->variables->name, |
| taggetOID_len) != 0)) { |
| break; |
| } |
| /* add to expValueTable */ |
| |
| *index = 0; |
| *(index + 1) = 0; |
| memcpy(index + 2, |
| response->variables->name + taggetOID_len, |
| (response->variables->name_length - |
| taggetOID_len) * sizeof(oid)); |
| expValueTable_add(expstorage, |
| objfound->expExpressionOwner, |
| objfound->expExpressionOwnerLen, |
| objfound->expExpressionName, |
| objfound->expExpressionNameLen, |
| index, |
| response->variables->name_length - |
| taggetOID_len + 2); |
| |
| next_OID = response->variables->name; |
| |
| next_OID_len = response->variables->name_length; |
| |
| |
| |
| |
| } else { |
| /* |
| * FAILURE: print what went wrong! |
| */ |
| if (status == STAT_SUCCESS) |
| fprintf(stderr, "Error in packet\nReason: %s\n", |
| snmp_errstring(response->errstat)); |
| else |
| snmp_sess_perror("snmpget", ss); |
| } |
| } while (TRUE); |
| |
| } |
| |
| } |
| |
| } |
| |
| |
| |
| /* |
| * var_expValueTable(): |
| */ |
| unsigned char * |
| var_expValueTable(struct variable *vp, |
| oid * name, |
| size_t *length, |
| int exact, size_t *var_len, WriteMethod ** write_method) |
| { |
| |
| struct expValueTable_data *StorageTmp = NULL; |
| |
| |
| |
| |
| DEBUGMSGTL(("expValueTable", "var_expValueTable: Entering... \n")); |
| |
| /* |
| * before we build valuetable we must free any other valutable if exist |
| */ |
| header_complex_free_all(expValueTableStorage, expValueTable_clean); |
| expValueTableStorage = NULL; |
| |
| |
| build_valuetable(); |
| |
| |
| /* |
| * this assumes you have registered all your data properly |
| */ |
| if ((StorageTmp = |
| header_complex(expValueTableStorage, vp, name, length, exact, |
| var_len, write_method)) == NULL) |
| return NULL; |
| |
| |
| /* |
| * this is where we do the value assignments for the mib results. |
| */ |
| switch (vp->magic) { |
| /* |
| * we only support counter32val |
| */ |
| |
| case EXPVALUECOUNTER32VAL: |
| StorageTmp->expValueCounter32Val = Evaluate_Expression(StorageTmp); |
| *var_len = sizeof(StorageTmp->expValueCounter32Val); |
| return (u_char *) & StorageTmp->expValueCounter32Val; |
| |
| case EXPVALUEUNSIGNED32VAL: |
| /* var_len = sizeof(StorageTmp->expValueUnsigned32Val); */ |
| /* return (u_char *) & StorageTmp->expValueUnsigned32Val; */ |
| return NULL; |
| |
| case EXPVALUETIMETICKSVAL: |
| /* var_len = sizeof(StorageTmp->expValueTimeTicksVal); */ |
| /* return (u_char *) & StorageTmp->expValueTimeTicksVal; */ |
| return NULL; |
| |
| case EXPVALUEINTEGER32VAL: |
| /* var_len = sizeof(StorageTmp->expValueInteger32Val); */ |
| /* return (u_char *) & StorageTmp->expValueInteger32Val; */ |
| return NULL; |
| |
| case EXPVALUEIPADDRESSVAL: |
| /* var_len = sizeof(StorageTmp->expValueIpAddressVal); */ |
| /* return (u_char *) & StorageTmp->expValueIpAddressVal; */ |
| return NULL; |
| |
| case EXPVALUEOCTETSTRINGVAL: |
| /* var_len = sizeof(StorageTmp->expValueOctetStringVal); */ |
| /* return (u_char *) & StorageTmp->expValueOctetStringVal; */ |
| return NULL; |
| |
| case EXPVALUEOIDVAL: |
| /* var_len = StorageTmp->expValueOidValLen; */ |
| /* return (u_char *) & StorageTmp->expValueOidVal; */ |
| return NULL; |
| |
| case EXPVALUECOUNTER64VAL: |
| /* var_len = sizeof(StorageTmp->expValueCounter64Val); */ |
| /* return (u_char *) & StorageTmp->expValueCounter64Val; */ |
| return NULL; |
| default: |
| ERROR_MSG(""); |
| return NULL; |
| } |
| } |
| |
| |
| |
| |
| |
| void |
| push(nodelink ** stack, unsigned long value) |
| { |
| nodelink *newnode; |
| newnode = (nodelink *) malloc(sizeof(nodelink)); |
| if (!newnode) { |
| printf("\nMemory allocation failure!"); |
| return; |
| } |
| newnode->data = value; |
| newnode->next = *stack; |
| *stack = newnode; |
| } |
| |
| unsigned long |
| pop(nodelink ** stack) |
| { |
| unsigned long value; |
| nodelink *top; |
| top = *stack; |
| *stack = (*stack)->next; |
| value = top->data; |
| free(top); |
| return value; |
| } |
| |
| int |
| priority(char operater) |
| { |
| switch (operater) { |
| case '*': |
| case '/': |
| return 4; |
| case '+': |
| case '-': |
| return 3; |
| case ')': |
| return 2; |
| case '(': |
| return 1; |
| default: |
| return 0; |
| } |
| } |
| |
| unsigned long |
| calculate(int operater, unsigned long a, unsigned long b) |
| { |
| switch (operater) { |
| case '+': |
| return (a + b); |
| case '-': |
| return (a - b); |
| case '*': |
| return (a * b); |
| case '/': |
| if (operater == '/' && b == 0) { |
| printf("\nDivision mustn\'t be 0!"); |
| exit(0); |
| } else |
| return (a / b); |
| } |
| return 0; |
| } |
| |
| unsigned long |
| get_operand(char *p, int *length) |
| { |
| char c[13]; |
| int i = 0, k = 1; |
| unsigned long result = 0; |
| while (*p <= 57 && *p >= 48) |
| c[i++] = *(p++); |
| *length += --i; |
| for (; i >= 0; i--) { |
| result += (c[i] - 48) * k; |
| k *= 10; |
| } |
| return result; |
| } |
| |
| int |
| operator_class(char c) |
| { |
| if (c <= 57 && c >= 48) |
| return 1; |
| if (c == 42 || c == 43 || c == 45 || c == 47) |
| return 2; |
| if (c == 41) |
| return 3; |
| if (c == 40) |
| return 4; |
| return 0; |
| } |
| |
| unsigned long |
| get_result(char *expr) |
| { |
| int position = 0; |
| unsigned long op = 0, a = 0, b = 0, result = 0; |
| char *expression; |
| expression = expr; |
| while (*(expression + position) != '\0' |
| && *(expression + position) != '\n') { |
| switch (operator_class(*(expression + position))) { |
| case 1: |
| push(&operand, get_operand(expression + position, &position)); |
| break; |
| case 2: |
| if (operater != NULL) |
| while (operater != NULL |
| && priority(*(expression + position)) <= |
| priority(operater->data)) { |
| a = pop(&operand); |
| b = pop(&operand); |
| op = pop(&operater); |
| push(&operand, calculate(op, b, a)); |
| } |
| push(&operater, *(expression + position)); |
| break; |
| case 3: |
| while (operater != NULL && operater->data != '(') { |
| a = pop(&operand); |
| b = pop(&operand); |
| op = pop(&operater); |
| push(&operand, calculate(op, b, a)); |
| } |
| if (operater->data == '(') |
| pop(&operater); |
| break; |
| case 4: |
| push(&operater, '('); |
| break; |
| default: |
| printf("\nInvalid character in expression:"); |
| a = 0; |
| while (*(expression + (int) a) != '\n' |
| && *(expression + (int) a) != '\0') { |
| if (a != position) |
| printf("%c", *(expression + (int) a)); |
| else |
| printf("<%c>", *(expression + (int) a)); |
| a++; |
| } |
| exit(0); |
| } /* end switch */ |
| position++; |
| } |
| while (operater != NULL) { |
| op = pop(&operater); |
| a = pop(&operand); |
| b = pop(&operand); |
| push(&operand, calculate(op, b, a)); |
| } |
| result = pop(&operand); |
| return result; |
| } |