273 lines
6.3 KiB
C
273 lines
6.3 KiB
C
|
/*
|
||
|
abCExprInt.c
|
||
|
By: Jeremy Rand
|
||
|
*/
|
||
|
|
||
|
|
||
|
#include <stdio.h>
|
||
|
#include <string.h>
|
||
|
#include <stdlib.h>
|
||
|
|
||
|
#include "abCMode.h"
|
||
|
|
||
|
#include "expr/abCExpr.h"
|
||
|
|
||
|
|
||
|
static abCalcExpr *abCalcExprIntParse(abCalcExpr *expr, char *buffer);
|
||
|
static char *abCalcExprIntFormat(abCalcExpr *expr, char *buffer);
|
||
|
|
||
|
|
||
|
static abCalcExprCallbacks gIntCallbacks = {
|
||
|
abCalcExprIntParse,
|
||
|
abCalcExprIntFormat
|
||
|
};
|
||
|
|
||
|
|
||
|
void abCalcExprIntInit(void)
|
||
|
{
|
||
|
abCalcRegisterExprType(abCalcExprTypeInt, &gIntCallbacks);
|
||
|
}
|
||
|
|
||
|
|
||
|
abCalcExpr *abCalcExprIntParse(abCalcExpr *expr, char *buffer)
|
||
|
{
|
||
|
abCalcModeIntBase base = abCalcModeGetBase();
|
||
|
abCalcIntType value = 0;
|
||
|
int len;
|
||
|
int offset = 1;
|
||
|
|
||
|
if (buffer == NULL)
|
||
|
return NULL;
|
||
|
|
||
|
if (expr == NULL)
|
||
|
return NULL;
|
||
|
|
||
|
len = strlen(buffer);
|
||
|
if (len < 2)
|
||
|
return NULL;
|
||
|
|
||
|
if (buffer[0] == '$') {
|
||
|
base = abCalcModeHexBase;
|
||
|
} else if ((buffer[0] == '0') &&
|
||
|
(buffer[1] == 'x')) {
|
||
|
base = abCalcModeHexBase;
|
||
|
offset = 2;
|
||
|
} else if (buffer[0] != '#')
|
||
|
return NULL;
|
||
|
|
||
|
switch (base) {
|
||
|
case abCalcModeBinBase:
|
||
|
for ( ; offset < len; offset++) {
|
||
|
value <<= 1;
|
||
|
switch (buffer[offset]) {
|
||
|
case '1':
|
||
|
value++;
|
||
|
break;
|
||
|
|
||
|
case '0':
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
return NULL;
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case abCalcModeOctBase:
|
||
|
for ( ; offset < len; offset++) {
|
||
|
value <<= 3;
|
||
|
switch (buffer[offset]) {
|
||
|
case '0':
|
||
|
case '1':
|
||
|
case '2':
|
||
|
case '3':
|
||
|
case '4':
|
||
|
case '5':
|
||
|
case '6':
|
||
|
case '7':
|
||
|
value += (buffer[offset] - '0');;
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
return NULL;
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case abCalcModeDecBase:
|
||
|
for ( ; offset < len; offset++) {
|
||
|
value *= 10;
|
||
|
switch (buffer[offset]) {
|
||
|
case '0':
|
||
|
case '1':
|
||
|
case '2':
|
||
|
case '3':
|
||
|
case '4':
|
||
|
case '5':
|
||
|
case '6':
|
||
|
case '7':
|
||
|
case '8':
|
||
|
case '9':
|
||
|
value += (buffer[offset] - '0');;
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
return NULL;
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case abCalcModeHexBase:
|
||
|
for ( ; offset < len; offset++) {
|
||
|
value <<= 4;
|
||
|
switch (buffer[offset]) {
|
||
|
case '0':
|
||
|
case '1':
|
||
|
case '2':
|
||
|
case '3':
|
||
|
case '4':
|
||
|
case '5':
|
||
|
case '6':
|
||
|
case '7':
|
||
|
case '8':
|
||
|
case '9':
|
||
|
value += (buffer[offset] - '0');;
|
||
|
break;
|
||
|
|
||
|
case 'a':
|
||
|
case 'A':
|
||
|
value += 10;
|
||
|
break;
|
||
|
|
||
|
case 'b':
|
||
|
case 'B':
|
||
|
value += 11;
|
||
|
break;
|
||
|
|
||
|
case 'c':
|
||
|
case 'C':
|
||
|
value += 12;
|
||
|
break;
|
||
|
|
||
|
case 'd':
|
||
|
case 'D':
|
||
|
value += 13;
|
||
|
break;
|
||
|
|
||
|
case 'e':
|
||
|
case 'E':
|
||
|
value += 14;
|
||
|
break;
|
||
|
|
||
|
case 'f':
|
||
|
case 'F':
|
||
|
value += 15;
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
return NULL;
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
expr->type = abCalcExprTypeInt;
|
||
|
expr->u.integer = value;
|
||
|
return expr;
|
||
|
}
|
||
|
|
||
|
|
||
|
char *abCalcExprIntFormat(abCalcExpr *expr, char *buffer)
|
||
|
{
|
||
|
abCalcModeIntBase base = abCalcModeGetBase();
|
||
|
int width = abCalcModeGetIntWidth();
|
||
|
abCalcIntType value;
|
||
|
char *ptr;
|
||
|
int gotFirstOne;
|
||
|
int i;
|
||
|
|
||
|
if (expr == NULL)
|
||
|
return NULL;
|
||
|
|
||
|
if (buffer == NULL)
|
||
|
return NULL;
|
||
|
|
||
|
if (expr->type != abCalcExprTypeInt)
|
||
|
return NULL;
|
||
|
|
||
|
value = expr->u.integer;
|
||
|
|
||
|
if (width < AB_CALC_EXPR_MAX_INT_WIDTH) {
|
||
|
value &= ((1l << width) - 1);
|
||
|
}
|
||
|
|
||
|
switch (base) {
|
||
|
case abCalcModeBinBase:
|
||
|
gotFirstOne = 0;
|
||
|
ptr = buffer;
|
||
|
*ptr = '#';
|
||
|
ptr++;
|
||
|
|
||
|
for (i = width - 1; i >= 0; i--) {
|
||
|
if ((value >> i) & 1) {
|
||
|
*ptr = '1';
|
||
|
ptr++;
|
||
|
gotFirstOne = 1;
|
||
|
} else {
|
||
|
if (gotFirstOne) {
|
||
|
*ptr = '0';
|
||
|
ptr++;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if (!gotFirstOne) {
|
||
|
*ptr = '0';
|
||
|
ptr++;
|
||
|
}
|
||
|
*ptr = ' ';
|
||
|
ptr++;
|
||
|
*ptr = 'b';
|
||
|
ptr++;
|
||
|
*ptr = '\0';
|
||
|
break;
|
||
|
|
||
|
case abCalcModeOctBase:
|
||
|
sprintf(buffer, "#%lo o", value);
|
||
|
break;
|
||
|
|
||
|
case abCalcModeDecBase:
|
||
|
sprintf(buffer, "#%lu d", value);
|
||
|
break;
|
||
|
|
||
|
case abCalcModeHexBase:
|
||
|
sprintf(buffer, "#%lX h", value);
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
return buffer;
|
||
|
}
|
||
|
|
||
|
|
||
|
void abCalcExprIntSet(abCalcExpr *expr, abCalcIntType value)
|
||
|
{
|
||
|
int width;
|
||
|
|
||
|
if (expr == NULL)
|
||
|
return;
|
||
|
|
||
|
width = abCalcModeGetIntWidth();
|
||
|
|
||
|
expr->type = abCalcExprTypeInt;
|
||
|
expr->u.integer = value;
|
||
|
|
||
|
if (width < AB_CALC_EXPR_MAX_INT_WIDTH) {
|
||
|
expr->u.integer &= ((1l << width) - 1);
|
||
|
}
|
||
|
}
|