rphone.cpp
来自「eC++编译器源码」· C++ 代码 · 共 436 行
CPP
436 行
#include <SYSTEM.h>
#include <RType.h>
#include <RTuple.h>
#include <RInterpret.h>
#include <Errors.h>
#include <SInOut.h>
#include <InOut.h>
#include <String.h>
#include <Calendar.h>
#include <CString.h>
//#include <stdio.h>
const unsigned int TPHONE=21; /*type id; must be system-unique for every type; numbers>=20 are available*/
const unsigned int COUNTRY=150; /*must be unique per type starting at 150; Extarct CountryCode */
const unsigned int AREA=151; /*Extract AreaCode */
const unsigned int LOCAL=152; /*Extract LocalNumber */
const unsigned int EXT=153; /*Extract Extension */
/* Internal Type representation */
const int dig3=1;
const int dig7=2;
const int cntry=3;
const int dig4=4;
const int CountryCode = 0;
const int AreaCode = 1;
const int LocalNumber = 2;
const int Extension = 3;
char ss[21];
unsigned int TypeLength;
typedef char Achar[50];
typedef char APhone[18];
/* Internal string structure supplement the stack operation */
/* Since the stack has no place for a string resulted from a conversion */
/* Here is where the conversion result of <phone"X-XXX-XXXXXX"> kept. */
APhone ExportBuf;
/* Internal structure for input parsing */
typedef struct {
char item[8];
int sect;
int len;
} buftype;
typedef buftype buffer[5];
/*returns width in bytes*/
unsigned int PhoneDeclarer(ADDRESS context, unsigned int requestedWidth) {
//the argument is the width requested in the "create" command
return 17; /*type size*/
};
/*Here is the code which convert input to the canonical phone number format */
/* Check whether a character is a phone digit. Only numeric values, uppercase
letter except 'Q' and 'Z' are consider as phone digits. */
boolean isAN(char c) {
int i;
i = ORD(c);
if ((i>47)&&(i<58)) {
return true;
} else if ((i>64)&&(i<91)) {
return true;
} else return false;
};
/* Convert alphabetical value to digit when input */
char AlphaConvert(char c) {
switch (c) {
case '0': return '0';
case '1': return '1';
case '2': case 'A': case 'B': case 'C': return '2';
case '3': case 'D': case 'E': case 'F': return '3';
case '4': case 'G': case 'H': case 'I': return '4';
case '5': case 'J': case 'K': case 'L': return '5';
case '6': case 'M': case 'N': case 'O': return '6';
case '7': case 'P': case 'R': case 'S': return '7';
case '8': case 'T': case 'U': case 'V': return '8';
case '9': case 'W': case 'X': case 'Y': return '9';
default: return ' ';
};
};
/* Get a space delimited token from input string */
int gettoken (char &s[], int pos, char &t[], int &q, int &p2) {
int i, j;
boolean lp;
j = pos;
i = 0;
q = 0;
while (!isAN(s[j]) && (s[j]!='\0') && (s[j]!='(')) { INC(j); };
if (s[j] == '(') lp = true;
while (!isAN(s[j]) && (s[j]!='\0')) { INC(j); };
while (isAN(s[j]) && (i<7)) {
t[i] = AlphaConvert(s[j]);
INC(i);
INC(j);
};
t[i] = '\0';
while (!isAN(s[j]) && (s[j]!='\0') && (s[j]!=')')) { INC(j); };
if (lp && (s[j] == ')')) {
if (i < 4) {
q = cntry;
p2 = j+1;
return i;
};
} else {
p2 = j;
if (i > 0) {
if (i > 4) q = dig7;
else if (i<4) q = dig3;
else q = dig4;
return i;
} else return 0;
};
};
/* Stages in parsing the input. */
boolean stage5(char &s[], int &pos, buffer &buf, int cnt) {
int q, p2;
buf[cnt].len = gettoken(s, pos, buf[cnt].item, q, p2);
if (buf[cnt].len > 0) {
return false;
} else {
buf[cnt-1].sect = Extension;
return true;
};
};
boolean stage4(char &s[], int &pos, buffer &buf, int cnt) {
int q, p2;
buf[cnt].len = gettoken(s, pos, buf[cnt].item, q, p2);
if (buf[cnt].len > 0) {
switch (q) {
case dig3: case dig4: buf[cnt].sect = Extension;
return stage5(s, p2, buf, cnt+1);
default: return false;
};
} else return true;
};
boolean stage3(char &s[], int &pos, buffer &buf, int cnt) {
int q, p2;
buf[cnt].len = gettoken(s, pos, buf[cnt].item, q, p2);
if (buf[cnt].len > 0) {
switch (q) {
case dig7: buf[cnt].sect = LocalNumber;
buf[cnt-1].sect = AreaCode;
return stage4(s, p2, buf, cnt+1);
default: return false;
};
} else return false;
};
boolean stage2(char &s[], int &pos, buffer &buf, int cnt) {
int q, p2;
buf[cnt].len = gettoken(s, pos, buf[cnt].item, q, p2);
if (buf[cnt].len > 0) {
switch (q) {
case dig3: buf[cnt].sect = AreaCode;
buf[cnt-1].sect = CountryCode;
return stage3(s, p2, buf, cnt+1);
case dig7: buf[cnt].sect = LocalNumber;
buf[cnt-1].sect = AreaCode;
return stage4(s, p2, buf, cnt+1);
default: return false;
};
} else return false;
};
boolean stage1 (char &s[], int &pos, buffer &buf, int cnt) {
int q,p2;
buf[cnt].len = gettoken(s, pos, buf[cnt].item, q, p2);
if (buf[cnt].len > 0) {
switch (q) {
case dig3: buf[cnt].sect = AreaCode;
return stage3(s, p2, buf, cnt+1);
case dig7: buf[cnt].sect = LocalNumber;
return stage4(s, p2, buf, cnt+1);
default: return false;
};
} else return false;
};
/* Read input string and convert it into canonical form which is going to
be stored at the tuple */
boolean PhoneRead(char &s[], char &out[]) {
char *p, *b, a[20];
Achar *x;
int i, j, cnt, q, p2, down;
boolean done;
buffer buf, *pbuf;
for (i=0;i<20;i++) a[i] = ' ';
for (i=0;i<4;i++) {
buf[i].item = "";
buf[i].sect = -1;
buf[i].len = 0;
};
j = 0;
cnt = 0;
buf[cnt].len = gettoken(s, j, buf[cnt].item, q, p2);
if (buf[cnt].len > 0) {
switch (q) {
case cntry: buf[cnt].sect = CountryCode;
done = stage1(s, p2, buf, cnt+1); break;
case dig4: buf[cnt].sect = Extension;
done = stage5(s, p2, buf, cnt+1); break;
case dig3: buf[cnt].sect = Extension;
done = stage5(s, p2, buf, cnt+1);
if (!done) {
buf[cnt].sect = -1;
done=stage2(s, p2, buf, cnt+1);
}; break;
case dig7: buf[cnt].sect = LocalNumber;
done = stage4(s, p2, buf, cnt+1); break;
default: done = false;
};
} else done = false;
if (done) {
for (i=0;i<4;i++) {
if (buf[i].sect >= 0) {
switch (buf[i].sect) {
case 0: down = 2; break;
case 1: down = 5; break;
case 2: down = 12; break;
case 3: down = 16; break;
};
for (j=0; j<buf[i].len; j++) {
a[down-j] = buf[i].item[buf[i].len-j-1];
};
};
};
a[17] = '\0';
out = a;
};
return done;
};
/* Get the canonical form from tuple and convert it into printable string */
void PhoneWrite(char &pr[], char &val[]) {
int i;
val[0] = '(';
val[4] = ')';
if (pr[5] != ' ') val[8] = '-';
else val[8] = ' ';
if (pr[16] != ' ') val[16] = '#';
else val[16] = ' ';
for (i=1;i<4;i++) {
val[i] = pr[i-1];
};
for (i=5;i<8;i++) {
val[i] = pr[i-2];
};
for (i=9;i<16;i++) {
val[i] = pr[i-3];
};
for (i=17;i<21;i++) {
val[i] = pr[i-4];
};
};
//this method performs all input/output conversions as well as constants
boolean PhoneIO (ADDRESS context, unsigned int method, pTuple p,
unsigned int index, unsigned int width, WORD &v[]) {
pOperand po;
Achar *val, *pr;
char *c;
APhone pval;
unsigned int i;
pr = ADDRESS(p)+LONG(index); //tuple+byte-offset is the field's address
if (method == LOAD) { //load binary value into an operand descriptor
po = ADR(v);
po->ot = TPHONE; //set operand type to Phone
po->il = width;
po->ioffset = index;
po->p = p;
return true; //indicate operand loaded successfully
} else if (method == STORE) { //copy Date from stack operand to tuple
// printf("STORE\n");
po = ADR(v);
if (po->ot != TPHONE) return false;
return true;
} else if (method == CONVERT) {
for (i=0;i<width;i++){
c = ADDRESS(pr) + LONG(i);
pval[i]= *c;
};
pval[width]='\0';
po = ADR(v);
po->ot = TPHONE;
po->ioffset = 0;
po->il = 17;
po->p = ADR(ExportBuf);
// printf("convert.export=%s\n", ExportBuf);
// return true;
if (PhoneRead(pval, ExportBuf)) return true;
else return false;
} else if ((method == WRITE) || (method == UPDATE)) {
val = ADR(v); //convert Date string to a binary value and store in a tuple
return PhoneRead(*val, *pr);
} else if (method == READ) {
val = ADR(v); //convert a binary date to a string for output
PhoneWrite(*pr, *val); /* %2u:%2u:%2u.%3c*/
return true;
} else if (method == CHECK) {
val = ADR(v);
return PhoneRead(*val, ExportBuf);
} else if (method == OPERATOR) { //invoked by parser to validate method calls
val = ADR(v);
if (CompareCS(*val, "country")==0) { //check if method name is supported
*val = "op=150;narg=2;"; //return method index and number-of-arguments+1
return true; //argument type checking is performed at runtime
} else if (CompareCS(*val, "area")==0) {
*val = "op=151;narg=2;";
return true;
} else if (CompareCS(*val, "local")==0) {
*val = "op=152;narg=2;";
return true;
} else if (CompareCS(*val, "ext")==0) {
*val = "op=153;narg=2;";
return true;
};
};
return false;
};
//the arguments are a method index and a pointer to an evaluation stack
void PhoneInvoke(unsigned int method, pStack ps) {
pOperand pl, pr;
APhone cr, cl, *xr, *xl;
DEC(ps->top); //decrement stack pointer
pl = ADR(ps->s[ps->top-1]); //create pointers to top two operands
pr = ADR(ps->s[ps->top]);
if (pr->ot != TPHONE) SoftwareError("PhoneInvoke:type not supported");
if (method == ORD(cmp)) { //if method is a comparison
if (pl->ot != TPHONE) SoftwareError("PhoneInvoke:type not supported");
xr = ADDRESS(pr->p) + LONG(pr->ioffset);
xl = ADDRESS(pl->p) + LONG(pl->ioffset);
strcpy(cr, *xr);
strcpy(cl, *xl);
cr[17]='\0';
cl[17]='\0';
pl->ot = Id("int"); //set the result type on top-of-stack to integer
pl->l = LONG(strcmp(cl, cr));
} else if (method == COUNTRY) {
pr->ot = 1;
pr->ioffset = 1;
pr->il = 3;
INC(ps->top);
} else if (method == AREA) {
pr->ot = 1;
pr->ioffset = 4;
pr->il = 3;
INC(ps->top);
} else if (method == LOCAL) {
pr->ot = 1;
pr->ioffset = 7;
pr->il = 7;
INC(ps->top);
} else if (method == EXT) {
pr->ot = 1;
pr->ioffset = 14;
pr->il = 4;
INC(ps->top);
} else {
SoftwareError("PhoneInvoke:method not supported");
};
};
void main(void) {
Register("phone", "Rphone", TPHONE, PhoneDeclarer, PhoneInvoke, PhoneIO);
//register the type name, module that implements the type; type code and three callback procedures
ss[0] = '\0';
TypeLength = 21; //specify the default field width
Format(TPHONE, WRITE, ss, TypeLength);
};
/*
<TelNumner> -> [<PrefixCode>]<PhoneNumber>
# Telephone numbers have optional prefix number but must have a
# phone number.
<PrefixCode> -> '('[<CountryCode>]')'<space>[<AreaCode>]<space> |
[<CountryCode>]<space><AreaCode><space> |
# A prefix number can be
# (1) combinations of CountryCode and AreaCode where
# the CountryCode is in parenthesis, regardless
whether both values are availabe or not;
# (2) combinations of CountryCode and AreaCode where
# the two are separated by space. Or
# (3) An AreaCode without a CountryCode.
<CountryCode> -> <digit>[<digit>][<digit>]
# The CountryCode is constructed of a minimum of one, maximum
# of 3 digits.
<AreaCode> -> <CountryCode>
# The AreaCode is in the same format as the CountryCode
<PhoneNumber> -> <LocalNumber><space><Extension> |
<LocalNumber> |
<Extension>
# A PhoneNumber can be
# (1) combinations of LocalNumber and Extension
# (2) a LocalNumber, or
# (3) an Extension
<LocalNumber> -> <digit><digit><digit><digit><digit>[<digit>][<digit>]
# LocalNumber is a minimum of 5, maximum of 7 digits code
<Extension> -> <digit>[<digit>][<digit>][<digit>]
# Extension is a minimum of 1, maximum of 4 digits code
<digit> -> '0'..'9', 'A'..'P', 'R'..'Y'
# digit is from '0' to '9' and uppercase letter except Q and Z.
<space> -> ~<digit>
# Any Non-digit character will be considered as space.
Sample Input:
Complete number (001)-800-CALLATTxMIKE
Number without CountryCode 601-2327396
Number without AreaCode (852)-6714620
Local Number only 2321234
Extension only 4567
Methods
There are 4 methods for the phone type:
phone.country(x) Extract the country code in character string form
phone.area(x) Extract the area code in character string form
phone.local(x) Extract the local number in character string form
phone.ext(x) Extract the extension in character string from
Since the results are returned as character string, queries using these methods will be:
print * from foo where phone.area(x)="800";
print * from foo where phone.ext(x)="4567";
Noticed that the right hand side of the comparisons are strings.
*/
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?