#include #include #include /* for function 'toupper' */ #include /* malloc */ #include "macro.h" #include "getcmd.h" #include "help.h" #include "tm.h" char look_word[MAC_WORD_LENGTH]; /* Returns a pointer to an empty macro structure. */ struct maclist *new_macro(struct maclist *mlist, int *status) { if (mlist == NULL) { mlist = (struct maclist *) malloc(sizeof (struct maclist)); mlist->num_macword = 0; mlist->list_name = NULL; mlist->root = NULL; } else /* clean out and reuse the old mlist */ { del_list_mac(mlist, status); if (*status != OK) return mlist; } mlist->root = (struct macword *) malloc(sizeof (struct macword)); if ( mlist->root == NULL) { *status = MEM_ERROR; free(mlist); return(NULL); } mlist->root->word = NULL; mlist->root->nextptr = NULL; mlist->root->prevptr = NULL; mlist->root->number = 0; mlist->num_macword = 0; return mlist; } void delete_macro(struct maclist *mlist, int *status) { del_list_mac(mlist, status); if (mlist != NULL) free(mlist); } /* Add a macro word to the end of the list. */ struct macword *new_macword(struct maclist *mlst, char *macstr, int *status) { struct macword *macptr,*oldptr; /* if (strlen(macstr) > MAC_WORD_LENGTH ) { *status = WORD_TOO_LONG; return(NULL); } */ /* if 'run' is placed in a macro you get an infinite recursive loop. */ if ( strcmp(macstr,"run") == 0 ) { *status = CANT_RUN_RUN; return(NULL); } /* make the first macword. */ if (mlst->root == NULL) /* first macword? Create a dummy.*/ { mlst->root = (struct macword *) malloc(sizeof (struct macword)); if ( mlst->root == NULL) { *status = MEM_ERROR; return(NULL); } mlst->root->word = NULL; mlst->root->nextptr = NULL; mlst->root->prevptr = NULL; mlst->root->number = 0; mlst->num_macword = 0; } macptr = mlst->root; while (macptr != NULL) /* search linked list for the end. */ { oldptr = macptr; macptr=macptr->nextptr; } /* add the new macro word to the end of the list.*/ macptr = (struct macword *) malloc(sizeof (struct macword)); if ( macptr == NULL) { *status = MEM_ERROR; return(NULL); } macptr->word = (char *) malloc (strlen(macstr) + 1); strcpy(macptr->word,macstr); if ( macptr->word == NULL) { *status = MEM_ERROR; free(macptr); return(NULL); } oldptr->nextptr = macptr; macptr->nextptr = NULL; macptr->prevptr = oldptr; macptr->number = ++mlst->num_macword; *status = OK; return(macptr); } /* Insert a macro word (char *macstr) on the linked list just after the word at location 'where' (int *where). */ void insert_macword(struct maclist *mlst, int *where, int *status, char *macstr) { struct macword *whereptr, *newptr, *macptr; if (strlen(macstr) > MAC_WORD_LENGTH ) { *status = WORD_TOO_LONG; return; } if (mlst->root == NULL) { *status = NO_MLIST; return; } if (strcmp(macstr,"run") == 0) { *status = CANT_RUN_RUN; return; } whereptr = mlst->root; while (whereptr != NULL) { if ( whereptr->number == *where) /* macstr goes after this one.*/ { newptr = (struct macword *) malloc(sizeof (struct macword)); if ( newptr == NULL) { *status = MEM_ERROR; return; } newptr->nextptr = whereptr->nextptr; newptr->prevptr = whereptr; newptr->word = (char *) malloc (strlen(macstr) + 1); strcpy(newptr->word,macstr); newptr->number = whereptr->number + 1; if (whereptr->nextptr != NULL) whereptr->nextptr->prevptr = newptr; whereptr->nextptr = newptr; macptr = newptr->nextptr; /* adjust the ordinals */ while (macptr != NULL) { macptr->number = macptr->prevptr->number + 1; macptr = macptr->nextptr; } *status = OK; return; } whereptr = whereptr->nextptr; } *status = CANT_INSERT; return; } /************************************************************/ /* function value is a pointer to a first occurance of macword 'str' after location 'where', if it exists, else it is NULL. */ int find_macword(struct maclist *mlst, int where, char* str, int *status) { struct macword *macptr; *status = WORD_NOT_FOUND; if (mlst->root == NULL) return(0); else macptr = mlst->root->nextptr; while (macptr != NULL ) { if ( strcmp(macptr->word,str) == 0 ) if ( macptr->number > where ) { *status = OK; return(macptr->number); } macptr = macptr->nextptr; } return(0); } /* list all the macwords. */ void list_mac(struct maclist *mlst, int *status) { struct macword *macptr; if (mlst->root == NULL) { *status = NO_MACRO; return; } macptr = mlst->root->nextptr; if (macptr == NULL) { *status = EMPTY_MACRO; return; } while (macptr != NULL ) { printf("%s ",macptr->word); macptr = macptr->nextptr; } printf("\n"); *status = OK; } /* list the macwords between locations 'lower' and 'upper'-- show the ordinal number. */ void edlist(struct maclist *mlst, int lower, int upper, int *status) { struct macword *macptr; if (mlst->root == NULL) { *status = NO_MACRO; return; } macptr = mlst->root->nextptr; if (macptr == NULL) { *status = EMPTY_MACRO; return; } while (macptr != NULL ) { if ( (macptr->number) >= lower && (macptr->number) <= upper ) printf("%d: %s\n",macptr->number, macptr->word); if ( (macptr->number) > upper ) break; macptr = macptr->nextptr; } *status = OK; } /* Remove a word from the list. */ void del_macword(struct maclist *mlst, int which, int *status) { struct macword *oldmacptr, *macptr; if (mlst->root==NULL) { *status = NO_MACRO; return; } oldmacptr = mlst->root; macptr = mlst->root->nextptr; if (macptr==NULL) { *status = EMPTY_MACRO; return; } while (macptr != NULL ) { if ( macptr->number == which ) { oldmacptr->nextptr = macptr->nextptr; if (macptr->nextptr != NULL) macptr->nextptr->prevptr = oldmacptr; if (macptr->word) free(macptr->word); free(macptr); mlst->num_macword--; macptr = oldmacptr->nextptr; while (macptr != NULL ) /* adjust the ordinals */ { macptr->number--; macptr = macptr->nextptr; } *status = OK; return; } oldmacptr = macptr; macptr = macptr->nextptr; } *status = WORD_NOT_FOUND; } /************************************************************/ /* remove all the macwords from a list. */ void del_all_mac(struct maclist *mlst, int *status) { struct macword *oldmacptr,*macptr; if (mlst->root == NULL) { *status = NO_MACRO; return; } macptr = mlst->root->nextptr; if (macptr == NULL) { *status = EMPTY_MACRO; return; } oldmacptr = macptr; while (macptr != NULL) { oldmacptr = macptr->nextptr; if (macptr->word) free(macptr->word); free(macptr); macptr = oldmacptr; } mlst->root->nextptr = NULL; mlst->num_macword = 0; *status = OK; } /* remove a macword list. Currently this routine is not being used. That should mean there is a problem with the code.*/ void del_list_mac(struct maclist *mlst, int *status) { del_all_mac(mlst, status); /* delete the macwords */ if ( *status == NO_MACRO ) /* there was no list */ return; else if ( *status == EMPTY_MACRO ) /* deleted an empty list */ *status=OK; free(mlst->root); mlst->root = NULL; if (mlst->list_name != NULL) { free(mlst->list_name); mlst->list_name = NULL; } } /* start a new macro list */ void set_mac(struct maclist *mlst, int *status) { char wordbuf[MAC_WORD_LENGTH]; printf("entering a macro... terminate with '.' after a space.\n"); while (1) { getcmd("",ans); if ( strcmp(ans,"exit") == 0 || strcmp(ans,".") == 0 ) break; if ( strchr(ans,' ') != 0) /* string has a space. add quotes. */ { wordbuf[0] = '"'; wordbuf[1] = '\0'; strcat(wordbuf,ans); strcat(wordbuf,"\""); } else { strcpy(wordbuf,ans); } new_macword(mlst,wordbuf,status); if ( *status != OK ) message("",*status); } } /* copy a word, drop commas and semi-colons except in quoted strings */ /**/ void nocomma_strcpy(char *to, char *from, int wordlen) { int i; if ( from[0] != '"' ) { for ( i=0; i<=wordlen; i++) { if( from[i] != ',' && from[i] != ';' ) { to[i] = from[i]; /* copy non-commas and non-semicolons */ if (from[i] == '\0' ) break; } else /* we have found a comma or a semicolon. drop it */ { to[i] = '\0'; break; } } } else /* 'from' is a quoted string. drop nothing but quotes */ { for ( i=0; i<=wordlen; i++) { to[i] = from[i+1]; if (from[i+1] == '"' ) { to[i] = '\0'; break; } } } } /* push the macro list on the command stack. tm will then run it automatically. */ /**/ void run_mac(struct maclist *mlst, int *status) { struct macword *macptr; char word[MAC_WORD_LENGTH]; int i; /* show_cmd("at start of run_mac\n"); DEBUG */ if (mlst->root == NULL) { *status = NO_MACRO; return; } macptr = mlst->root->nextptr; if (macptr == NULL) { *status = EMPTY_MACRO; return; } if ( macptr->nextptr == NULL ) /* only one token on the list */ { nocomma_strcpy(word,macptr->word,MAC_WORD_LENGTH); pushcmd(word); *status = OK; return; } /* need to load the command stack with macro words in reverse order because of the way pushcmd() works */ while (macptr->nextptr != NULL) /* find the end of the list */ macptr = macptr->nextptr; while (macptr != mlst->root) /* load the command stack */ { nocomma_strcpy(word,macptr->word,MAC_WORD_LENGTH); pushcmd(word); macptr = macptr->prevptr; } *status = OK; return; } /* simple macro list editor. */ /**/ void edmacro(struct maclist *mptr) { char look_word[MAC_WORD_LENGTH]; int where,inum; int lower,upper,i; int status; look_word[0] = '\0'; while (1) { getcmd("ed> ",ans); if ( ans[0] == 0 ); /* flush invalid input */ else if (iscmd (ans,"exit") || iscmd (ans,".") ) break; else if (iscmd (ans,"f*ind")) { if ( look_word[0]=='\0' || morecmd() == 1 ) { getcmd("find what word? ",ans); strcpy(look_word,ans); where = 0; where = find_macword(mptr, where,look_word,&status); if (status != OK) message("",status); else edlist(mptr, where,where+10,&status); } else /* look for other instances of 'look_word ' */ { where = find_macword(mptr,where,look_word,&status); if (status != OK) message("",status); else edlist(mptr, where,where+10,&status); } } else if (iscmd (ans,"l*ist")) { if ( morecmd() > 0 ) { if (getint("",&lower) == OK) edlist(mptr,lower,lower+20,&status); else edlist(mptr,1,10000,&status); } else edlist(mptr, 1,10000,&status); } else if (iscmd (ans,"i*nsert")) { if ( getint("insert where? ",&inum) == OK ) { getcmd("insert what? ",ans); insert_macword (mptr, &inum, &status, ans); if (status != OK) { message("",status); break; } while ( morecmd() != 0 ) { getcmd("",ans); inum++; insert_macword (mptr, &inum, &status, ans); if (status != OK) break; } if (status != OK) message("",status); } } else if (iscmd (ans,"d*elete")) { if (getint("delete which? ",&inum) == OK) { if ( morecmd() == 1 ) { lower = inum; while ( getint("",&upper) !=OK ); /* force return of integer*/ for ( i=lower; i<=upper; i++ ) { del_macword(mptr, lower, &status ); if (status != OK) message("",status); } } else { del_macword(mptr, inum, &status ); if (status != OK) message("",status); } } } else if (iscmd (ans,"h*elp") || iscmd (ans,"?") ) get_help("tm edmacro"); else if (iscmd(ans,"#") ) flushcmd("","",0); else flushcmd("invalid or ambiguous -> ",ans,1); } }