#include #include #include /* for function 'toupper' */ #include /* malloc */ #include "quint.h" #include "tm.h" /************************************************************/ /* function value is pointer to a quint if it exists, else it is NULL. */ struct quint *find_quint(struct qlist *qlst, char a, char b, int *status) { struct quint *qptr; *status = NON_HAVE_STATE; qptr = qlst->root; if (qlst->root == NULL) return(NULL); else qptr = qlst->root->nextptr; while (qptr != NULL ) { if ( qptr->current_state == a ) { if ( qptr->current_symbol == b ) { *status = OK; return(qptr); } *status = STATE_BUT_NO_SYM; } qptr = qptr->nextptr; } return(NULL); } /* insert a new quintuple on the quintuple list */ struct quint *new_quint(struct qlist *qlst, char *qstring, char *comment, int *status) { char qbuff[5]; struct quint *qptr,*oldptr; if (strlen(qstring) != 5 ) { if ( strcmp(qstring,"exit") == 0 || strcmp(qstring,".") == 0 ) *status = OK; else *status = NEEDS_5; return(NULL); } strncpy(qbuff,qstring,5); /* quintuples must terminate in 'L', 'R', or '0': */ qbuff[4] = toupper(qbuff[4]); if ( qbuff[4] != 'R' && qbuff[4] != 'L' && qbuff[4] != '0') { *status = END_IN_LR; return(NULL); } /* quintuples on a given list must be unique up to the first 2 characters*/ find_quint( qlst, qbuff[0], qbuff[1], status ); if ( *status == OK ) /* quintuple already exists */ { /* ... no duplicate quintuples allowed */ *status = QEXISTS; return(NULL); } /* make the new quintuple. */ if (qlst->root == NULL) /* first quintuple? Create a dummy.*/ { qlst->root = (struct quint *) malloc(sizeof (struct quint)); if (qlst->root == NULL) { *status = OUT_OF_MEMORY; return NULL; } memset(qlst->root, 0, sizeof(struct quint)); qlst->root->nextptr = NULL; } qptr = qlst->root; while (qptr != NULL) /* search linked list for new slot */ { oldptr = qptr; qptr=qptr->nextptr; } qptr = (struct quint *) malloc( sizeof (struct quint)); if (qptr == NULL) { *status = OUT_OF_MEMORY; return NULL; } memset(qptr, 0, sizeof(struct quint)); oldptr->nextptr = qptr; qptr->current_state = qbuff[0]; qptr->current_symbol = qbuff[1]; qptr->next_symbol = qbuff[2]; qptr->next_state = qbuff[3]; qptr->move = qbuff[4]; qptr->brk = 0; qptr->num_used = 0; qptr->nextptr = NULL; qptr->comment = NULL; qlst->num_quint++; *status = OK; /* Do comments as an afterthought so we can return anytime. */ if (comment == NULL) return qptr; /* Trim leading and trailing white space. */ comment += strspn(comment, " \n\t"); if (*comment) { char *szTmp=comment + strlen(comment); while (comment <= szTmp && strchr(" \t\n", *szTmp)) *(szTmp--) = '\0'; } /* If we run out of space here, return quietly with NULL comment. */ if (*comment){ qptr->comment = (char *) malloc(strlen(comment) + 1); strcpy( qptr->comment, comment); } /* *status = COM_TOO_LONG; */ return(qptr); } void quint_comment(struct quint *qptr, char *comment) { if (qptr == NULL) return; if (qptr->comment != NULL) { free(qptr->comment); qptr->comment = NULL; } if (comment != NULL) { qptr->comment = (char *) malloc(strlen(comment) + 1); strcpy( qptr->comment, comment); } return; } void print_quint(struct quint *qptr, struct qlist *qlst) { printf("%c%c%c%c%c",qptr->current_state, qptr->current_symbol, qptr->next_symbol, qptr->next_state, qptr->move); if (qlst->show_iter) printf(" %d",qptr->num_used); if (qlst->show_comment) if (qptr->comment) printf(" %s",qptr->comment); printf("\n"); } /* list all the quintuples. */ void list_quints(struct qlist *qlst, int *status) { struct quint *qptr; if (qlst->root == NULL) { *status = NO_QLIST; return; } qptr = qlst->root->nextptr; if (qptr == NULL) { *status = EMPTY_QLIST; return; } while (qptr != NULL ) { print_quint(qptr,qlst); qptr = qptr->nextptr; } *status = OK; } /* Remove a quintuple from the list. */ void del_quint(struct qlist *qlst, char state, char symbol, int *status) { struct quint *oldqptr, *qptr; if (qlst->root==NULL) { *status = NO_QLIST; return; } oldqptr = qlst->root; qptr = qlst->root->nextptr; if (qptr==NULL) { *status = EMPTY_QLIST; return; } while (qptr != NULL ) { if ( qptr->current_state == state && qptr->current_symbol ==symbol) { oldqptr->nextptr = qptr->nextptr; if (qptr->comment) free(qptr->comment); free(qptr); *status = OK; qlst->num_quint--; return; } oldqptr = qptr; qptr = qptr->nextptr; } *status = NO_SUCH_Q; } /************************************************************/ /* remove all the quintuples from a list. */ void del_all_quint(struct qlist *qlst, int *status) { struct quint *oldqptr,*qptr; if (qlst->root == NULL) { *status = NO_QLIST; return; } qptr = qlst->root->nextptr; if (qptr == NULL) { *status = EMPTY_QLIST; return; } oldqptr = qptr; while (qptr != NULL) { oldqptr = qptr->nextptr; free(qptr); qptr = oldqptr; } qlst->root->nextptr = NULL; qlst->num_quint = 0; *status = OK; } /* remove a quintuple list (DMH: replaced = with == inside ifs) */ void del_list_quint(struct qlist *qlst, int *status) { del_all_quint(qlst, status); /* delete the quintuples */ if ( *status == NO_QLIST ) /* there was no list */ return; else if ( *status == EMPTY_QLIST ) /* deleted an empty list */ *status=OK; free(qlst->root); qlst->root = NULL; } /* Set iteration count of all quintuples to zero */ void zero_quint_iter(struct qlist *qlst) { struct quint *qptr; if (qlst->root == NULL) return; qptr = qlst->root->nextptr; if (qptr == NULL) return; while (qptr != NULL ) { qptr->num_used = 0; qptr = qptr->nextptr; } } /****************************************************************************/ /* Create and delete quintuple lists */ /* Create a QList */ struct qlist *new_qlist(int *status) { struct qlist *newlist=NULL; newlist = malloc(sizeof(struct qlist)); if (newlist == NULL) { *status = OUT_OF_MEMORY; return NULL; } memset(newlist, 0, sizeof(struct qlist)); newlist->root = (struct quint *) malloc(sizeof (struct quint)); if (newlist->root == NULL) { *status = OUT_OF_MEMORY; return NULL; } *status = OK; memset(newlist->root, 0, sizeof(struct quint)); newlist->root->nextptr = NULL; return newlist; } /* remove a quintuple list completely, including the base struct. */ void del_qlist(struct qlist *qlst, int *status) { if (qlst == NULL) { *status = NO_QLIST; return; } del_all_quint(qlst, status); /* delete the quintuples */ if ( *status == NO_QLIST || *status == EMPTY_QLIST ) /* deleted an empty or rootless list */ *status=OK; if (qlst->root != NULL) free(qlst->root); qlst->root = NULL; free(qlst); /* Delete the basic structure */ }