/************************************************************************ * * * name: Renumber.e * * author: Stephen Degler * * last update: 10-Sep-1989 14:15:36 * * description: renumbers labels ending in digits and fixes * * up the references to them * ************************************************************************/ #include /* Check out procedure bounds */ #define MAX_IDENTIFIER 32 /* longest symbol length in MASM */ #define TRUE 1 #define FALSE 0 struct ref_list { struct ref_list *next_ref; int *ref_location; /* buffer location of this reference */ }; struct label_header { struct label_header * next_label; /* link to next label */ int * where_found; /* buffer location where the label was found */ struct ref_list * reference_list; /* list of references to a symbol */ char *label_name; /* pointer to symbol itself */ }; struct label_header * newlabel(); struct label_header * first_label; int *procedure_start; int *procedure_end; int *initial_loc; command renumber() { procedure_start = alloc_spot(); procedure_end = alloc_spot(); initial_loc = alloc_spot(); *initial_loc = point; if ( inside_procedure() ) { first_label = 0; if (! find_all_labels() ) say("no labels found !"); else { find_all_label_references(); sort_labels(); free_data(first_label); point = *initial_loc; } } free_spot(initial_loc); free_spot(procedure_start); free_spot(procedure_end); } /* regular expression to find_labels */ char label_regex[]= "^[ \t]*!([A-Za-z_$#@]+([0-9]+))((:)|([ \t]+label[ \t]+))"; find_all_labels() { int x=FALSE; point = *procedure_start; if ( re_compile(1,label_regex) ) { say("renumber: regular expression compile failed"); return(FALSE); } while ( point <= *procedure_end ) { findlabel(); nl_forward(); x = TRUE; } return(x); } /* regular expression for finding references char ref_regex[]= "^[ \t]*[A-Za-z0-9_$#@:]*[ \t]*(([a-zA-Z]+[ \t]+[a-zA-Z],)|([a-zA-Z]+[ \t]+))"; */ find_all_label_references() { struct label_header *l; char tempbuf[256]; l = first_label; while ( l ) { sprintf(tempbuf,"^(.)*(%s)(.)*$",l->label_name); if ( re_compile(1,tempbuf) ) { say("renumber: regular expression compile failed"); return; } point = *procedure_start; while ( point < *procedure_end ) { find_label_ref(l); nl_forward(); } l = l->next_label; } } /* recursively free all malloc'ed data structures and spots */ free_data(lh) struct label_header * lh; { if ( lh->next_label != 0 ) free_data(lh->next_label); if ( lh->reference_list ) free_ref_list(lh->reference_list); free(lh->label_name); free_spot(lh->where_found); free(lh); } free_ref_list(p) struct ref_list *p; { if( p->next_ref != 0 ) free_ref_list(p->next_ref); free_spot(p->ref_location); free(p); } /************************************************************************ * * * Findlabel - * * Searches forward for valid label identifiers. * * Upon finding a label, a label_header structure is initalized and * * added to the list of label_headers. If no list exists, one will * * started. * * returns 1 if label found * * returns 0 if match beyond procedure bounds or search fails * ************************************************************************/ findlabel() { struct label_header *l; char * c; if ( re_match() == -1 ) return (FALSE); else if ( ( l = newlabel()) == 0 ) exit(-1); grab(find_group(1,1),find_group(2,0),l->label_name); return(TRUE); } struct label_header * newlabel() { struct label_header * p; struct label_header * q; if ( (p = (struct label_header *) malloc(sizeof(struct label_header))) == 0 ) { say("renumber: function newlabel malloc failed"); return(FALSE); } if ( first_label == 0 ) first_label = p; else { q = first_label; while ( q->next_label != 0) q = q->next_label; /* go to end of list */ q->next_label=p; /* and stuff the new */ } p->next_label = 0; p->where_found = alloc_spot(); p->reference_list = 0; if ( (p->label_name = malloc(MAX_IDENTIFIER+1)) == 0 ) { say("renumber: function newlabel malloc failed"); return(FALSE); } return(p); } /************************************************************************ * * * find_label_ref(l) * * builds a regular expression based on the symbol passed in l * * this is the simple version which will work in the following cases: * * jmp labelname * * mov ax,labelname * * * ************************************************************************/ find_label_ref(l) struct label_header * l; { struct ref_list *p, *q; if ( re_match() == -1 ) return(FALSE); /* failure */ if ( find_group(2,1) == *l->where_found ) return(FALSE); /* more failure - found label declaration */ /* we matched so add to the referece list */ if ( (p = (struct ref_list *) malloc(sizeof(struct ref_list) ) ) == 0 ) { say("renumber: malloc failed adding to reference list "); return(FALSE); } p->next_ref = 0; p->ref_location = alloc_spot(); *p->ref_location = find_group(2,1); if ( l->reference_list == 0 ) l->reference_list = p; else { q = l->reference_list; while ( q->next_ref != 0 ) q = q->next_ref; q->next_ref = p; } return(TRUE); } /************************************************************************ * * * inside_procedure() * * ensures that point is bounded by a procedure declaration above it * * and a corresponding endp below it * * * ************************************************************************/ char proc_regex[]="^![ \t]*([A-Za-z0-9@#$_])+[ \t]+((endp)|(proc))"; int inside_procedure() { int *pointsave; int tempbuf[5]; pointsave = alloc_spot(); *pointsave = point; /* save point */ *procedure_start = 0; /* init these global variables */ *procedure_end = 0; if ( ! re_search(-1,proc_regex) ) { say("renumber: could not find procedure declarations"); return(FALSE); } grab(find_group(2,1),find_group(2,0),tempbuf); if ( strcmp(tempbuf,"proc") ) { say("renumber: found end declaration befor beginning"); return(FALSE); } *procedure_start = point; nl_forward(); if ( ! re_search(1,proc_regex) ) { say("renumber: could not find procedure declarations"); return(FALSE); } grab(find_group(2,1),find_group(2,0),tempbuf); if ( strcmp(tempbuf,"endp") ) { say("renumber: block nesting error"); return(FALSE); } *procedure_end = point; return(TRUE); point = *pointsave; } /************************************************************************* * * sort_labels * this is the first go at label rearranging. A simple push down sort * will be the first sorting algorith; We can get fancy later. * The numeric portion at the end of each symbol is converted to an int * with atoi and placed in an array of ints. * **************************************************************************/ sort_labels() { int *array_ptr; /* pointer to the array to sort */ char * i; /* pointer to char to find numeric portion */ int j, k, l, indx; /* not very interesting integers */ int tmpval; /* temp int holder */ int count; /* number of symbols and the size of the array to allocate */ struct label_header *p; struct ref_list *r; int * oldpoint = alloc_spot(); /* the following loop counts the total number of label structures */ p=first_label; for(count=1;p->next_label != 0;count++) p=p->next_label; /* now allocate an array of ints for the sort */ if ( ( array_ptr = (int *) malloc(count * sizeof(int))) == 0 ) { say("renumber: malloc failed in sort_labels"); return(FALSE); } /* fill out the array */ p = first_label; j = 0; while ( p ) { i = p->label_name; i += (strlen(p->label_name) - 1 ); while(isdigit(*i)) --i; ++i; array_ptr[j] = atoi(i); p = p->next_label; j++; } /* now sort array */ for ( k=count-1; k > 0; k-- ) { tmpval = array_ptr[0]; indx = 0; for( l = 1; l <= k; l++ ) { if ( array_ptr[l] > tmpval ) { tmpval = array_ptr[l]; indx = l; } } array_ptr[indx] = array_ptr[k]; array_ptr[k] = tmpval; } /* sort is finished! now stuff the values back in */ p = first_label; j = 0; while ( p ) { r = p->reference_list; while( r ) { point = *r->ref_location; point += (strlen(p->label_name)); *oldpoint = point; --point; while( isdigit(curchar()) ) --point; ++point; delete(point,*oldpoint); bprintf("%d",array_ptr[j]); r = r->next_ref; } point = *p->where_found; point += (strlen(p->label_name) ); *oldpoint = point; --point; while( isdigit(curchar()) ) --point; ++point; delete(point,*oldpoint); bprintf("%d",array_ptr[j]); p = p->next_label; j++; } free_spot(oldpoint); } int atoi(c) char * c; { int i; i = 0; while ( *c != 0 ) { if ( ! isdigit(*c) ) return(-1); else { i *= 10; i += *c - 0x30; c++; } } return(i); }