Listing 2 The message interpreter and assembler for the embedded controller, implemented on a PC
/* pars.c */ /* no copyrights claimed */ #include <stdio.h> #include <stdlib.h> #include <ctype.h> #include <string.h> #include "parsdef.h" static toDoList toDo[MAX_STATEMENTS]; static char stringPool[STRINGPOOL]; static char *pPool, *poolEnd; static char message[MESSAGELENGTH]; static char *messList[]= { "EMPTY","error","empty","assign","request", "to_eeprom","is","command","integer","float", "name","name_error","op_error","val_error", "end_error","pool_error" }; main() { while(1) { pPool= stringPool; poolEnd= stringPool+STRINGPOOL-1; printf("\nmessage: "); gets(message); if(message[0]=='.') break; Parse(message, toDo); PrintToDo(toDo); DoCommands(toDo); } } /* first, the parsing */ void Parse(char *message, toDoList *pToDo) { char *pC, token[MAX_TOKEN_LEN+1]; int type, i; pC= message; for(i=0; i<MAX_STATEMENTS; i++) { (pToDo+1)->command= EMPTY; /* mark end */ if(*pC=='\0'){pToDo->command= EMPTY; return;} /* get name */ pC= GetNextToken(pC, token, &type); if(StoreToken(&pToDo->name, token) != 0) { pToDo->command=POOL_ERROR; return; } if((type==ERROR)||(type!=NAME)) { pToDo->command= NAME_ERROR; return;} if(*pC=='\0') {pToDo->command=EMPTY; return;} /* get operator */ pC= GetNextToken(pC, token, &type); if(type==ERROR) {pToDo->command=OP_ERROR; return;} pToDo->command= type; /* get value */ if((type==ASSIGN)||(type==TO_EEPROM)|| (type==IS)) { if(*pC=='\0') {pToDo->command=VAL_ERROR; return;} pC= GetNextToken(pC, token, &type); pToDo->type= type; if(type==INTEGER) pToDo->value= atoi(token); else {pToDo->command= VAL_ERROR; return;} } else pToDo->type= INTEGER; if(pToDo->command== EMPTY) return; pToDo++; } pToDo->command= END_ERROR; return; } char *GetNextToken(char *begin, char *token, int type) { char *pC, *pT; int i; pC= begin; pT= token; *token='\0'; *type= EMPTY; if(*pC == '\0') {return pC;} /* remove leading spaces */ while(*pC=='') pC++; if(*pC=='\0') return pC; if(isalpha(*pC)) { /* name */ *type= NAME; *pT++= *pC++; for(i=1; i<MAX_TOKEN_LEN; i++) { if((isalpha(*pC)) || (isdigit(*pC)) ||(*pC=='_')) *pT++= *pC++; else { *pT= '\0'; return pC; } } *type= ERROR; return pC; } else if((isdigit(*pC))||(*pC=='+')||) (*pC=='-')) { /* number */ *pT++= *pC++; for(i=1; i<MAX_TOKEN_LEN; i++) { if(isdigit(*pC)) *pT++= *pC++; else { *pT= '\0'; *type= INTEGER; return pC; } } *type= ERROR; return pC; } else if(*pC== '=') *type= ASSIGN; else if(*pC== '?') *type= REQUEST; else if(*pC== '>') *type= TO_EEPROM; else if(*pC== ':') *type= IS; else if(*pC== '!') *type= COMMAND; else {*type= ERROR; return ++pC;} return ++pC; } int StoreToken(char **ppName, char *token) { int length; *ppName= pPool; length= strlen(token)+1; if((pPool+length)>=poolEnd) return -1; strcpy(pPool, token); pPool+= length; return 0; } /* and now, the action */ static symTabEntry symTab[]= { {"reset" , 0 , Reset, -1}, {"status" , 35 , NULL , -1}, {"temp" , 16 , NULL , 20} }; void PrintToDo(toDoList *toDo) { while(toDo->command != EMPTY) { printf("\n %s %s '%s'", messList[toDo->command], messList[toDo->type], toDo->name); if(toDo->type==INTEGER) printf(" %d", toDo->value); toDo++; } } int SymCmp(symTabEntry *a, symTabEntry *b) { return strcmp(a->name, b->name); } symTabEntry *FindSymbol(char *pName) { symTabEntry dummy, *p; dummy.name= pName; p= (symTabEntry*) bsearch(&dummy, symTab, sizeof(symTab)/sizeof(symTabEntry), sizeof(symTabEntry), (int(*)(const void*, const void*))SymCmp); return p; } char *Reset(char *pC) { printf("\nExecuting 'Reset'"); return pC; } void DoCommands(toDoList *pToDo) { char *txBuffer, *pTx; txBuffer= pTx= TxBuffer(); *pTx= '\0'; while(pToDo->command != EMPTY) { switch(pToDo->command) { case ERROR: case NAME_ERROR: case OP_ERROR: case VAL_ERROR: case END_ERROR: case POOL_ERROR: pTx= SayError(pToDo, pToDo->command, pTx); break; case ASSIGN: pTx= Assign(pToDo, pTx); break; case REQUEST: pTx= Request(pToDo, pTx); break; case TO_EEPROM: pTx= ToEeprom(pToDo, pTx); break; case COMMAND: pTx= RunCommand(pToDo, pTx); break; default: break; } ++pToDo; } printf("\ntxBuffer: '%s'\n", txBuffer); } char *SayError(toDoList *pToDo, int err, char *pC) { char str[MAX_TOKEN_LEN+1], *pS; pS= pToDo->name; while(*pC++=*pS++); pC--; *pC++='#'; sprintf(str,"%-d", err); pS= str; while(*pC++= *pS++); return --pC; } char *Assign(toDoList *pToDo, char *pTx) { symTabEntry *pSym; pSym= FindSymbol(pToDo->name); if(pSym==NULL) { pTx= SayError(pToDo, UNDEF_SYMB, pTx); return pTx; } if(pToDo->type==INTEGER) pSym->ival= pToDo->value; if(pSym->func!=NULL) pTx= (*pSym->func)(pTx); return pTx; } char *Request(toDoList *pToDo, char *pTx) { symTabEntry *pSym; char *pS, str[MAX_TOKEN_LEN+1]; pSym= FindSymbol(pToDo->name); if(pSym==NULL) { pTx= SayError(pToDo, UNDEF_SYMB, pTx); return pTx; } pS= pToDo->name; while(*pTx++=*pS++); pTx--; *pTx++= '='; if(pToDo->type==INTEGER) sprintf(str,"%-d", pSym->ival); pS= str; while(*pTx++=*pS++); if(pSym->func!=NULL) pTx= (*pSym->func)(pTx); return --pTx; } char *ToEeprom(toDoList *pToDo, char *pTx) { symTabEntry *pSym; pSym= FindSymbol(pToDo->name); if(pSym==NULL) { pTx= SayError(pToDo, UNDEF_SYMB, pTx); return pTx; } if(pSym->eeOffset<O) { pTx= SayError(pToDo, NOT_EEPROM, pTx); return pTx; } if(pToDo->type==INTEGER) { pSym->ival= pToDo->value; WriteEeprom(pSym, INTEGER]; } if(pSym->func!=NULL) pTx= (*pSym->func)(pTx); return pTx; } char *RunCommand(toDoList *pToDo, char *pTx) { symTabEntry *pSym; pSym= FindSymbol(pToDo->name); if(pSym==NULL) { pTx= SayError(pToDo, UNDEF_SYMB, pTx); return pTx; } if(pSym->func!=NULL) pTx= (*pSym->func)(pTx); else { pTx=SayError(pToDo, UNDEF_FUNC, pTx); return pTx; } return pTx; } char *TxBuffer(void) { static char buffer[200]; return buffer; } void WriteEeprom(symTabEntry *pSym, int type) { if(type==INTEGER) printf( "\nTo EE, type: %d off: %d val: %d\n", type, pSym->eeOffset, pSym->ival); return; } /* End of File */