diff options
author | Kenneth G Raeburn <raeburn@mit.edu> | 1990-05-16 21:24:43 +0000 |
---|---|---|
committer | Kenneth G Raeburn <raeburn@mit.edu> | 1990-05-16 21:24:43 +0000 |
commit | d88feb612341af9103aa26d1f1149ef9c99c1943 (patch) | |
tree | 3318c93fc2dda2998babd28629f5134c6bd91df3 /zwgc | |
parent | 21d389cbedba524b5d94abbfbcf00c9990859880 (diff) |
[marc] rewrote much of handling of requoting of environments and delimiters
for PROTECT routine
Diffstat (limited to 'zwgc')
-rw-r--r-- | zwgc/formatter.c | 239 |
1 files changed, 112 insertions, 127 deletions
diff --git a/zwgc/formatter.c b/zwgc/formatter.c index 16d20cd..59627f5 100644 --- a/zwgc/formatter.c +++ b/zwgc/formatter.c @@ -167,6 +167,59 @@ static char brackets[]="()<>[]{}@"; static char *openbracket[]={"@<","@<","@[","@[","@{","@{","@(","@(","@("}; static char *closebracket[]={">",">","]","]","}","}",")",")",")"}; +int not_contains(str, set) + string str; + character_class set; +{ + while (*str && ! set[*str]) str++; + return (! *str); +} + +static int pure_text_length(text,terminator) + char *text; + char terminator; +{ + int len=0; + + while (1) { + while (*text!='@' && *text!=terminator && *text) { + text++; + len++; + } + + if (*text!='@') + return(len); + + if (*(text+1)=='@') { + text++; + len++; + } else if (env_length(text+1) != -1) + return(len); + + text++; + len++; + } +} + +static char otherside(opener) +char opener; +{ + switch (opener) { + case '(': + return(')'); + case '{': + return('}'); + case '[': + return(']'); + case '<': + return('>'); + } + +#ifdef DEBUG + abort(); +#endif +} + /* the char * that str points to is free'd by this function. * if you want to keep it, save it yourself */ @@ -179,8 +232,11 @@ string verbatim(str) if (strlen(str) == pure_text_length(str,0)) { /* No environments, so consider the fast-and-easy methods */ - if (not_contains(str,allbracket_set)) - return(string_Copy(str)); + if (not_contains(str,allbracket_set)) { + temp = string_Copy(str); + free(str); + return(temp); + } if (not_contains(str,abracket_set)) { temp=(char *) malloc((len=strlen(str))+4); @@ -189,6 +245,7 @@ string verbatim(str) bcopy(str,temp+2,len); temp[len+2]='>'; temp[len+3]='\0'; + free(str); return(temp); } if (not_contains(str,sbracket_set)) { @@ -198,6 +255,7 @@ string verbatim(str) bcopy(str,temp+2,len); temp[len+2]=']'; temp[len+3]='\0'; + free(str); return(temp); } if (not_contains(str,cbracket_set)) { @@ -207,6 +265,7 @@ string verbatim(str) bcopy(str,temp+2,len); temp[len+2]='}'; temp[len+3]='\0'; + free(str); return(temp); } if (not_contains(str,paren_set)) { @@ -216,6 +275,7 @@ string verbatim(str) bcopy(str,temp+2,len); temp[len+2]=')'; temp[len+3]='\0'; + free(str); return(temp); } } @@ -240,147 +300,72 @@ string verbatim(str) or the default terminator \0. The text will not be modified, and @@ will be counted twice */ -static int pure_text_length(text,terminator) - char *text; - char terminator; -{ - int len=0; - - while (1) { - while (*text!='@' && *text!=terminator && *text) { - text++; - len++; - } - - if (*text!='@') - return(len); - - if (*(text+1)=='@') { - text++; - len++; - } else if (env_length(text+1) != -1) - return(len); - - text++; - len++; - } -} - -/* returns length of "block" pointed to by str, where a block is a - * combination of pure strings and environments, surrounded by one - * valid environment. If str does not point to an environment - * then -1 is returned. No replacement of @@ is made. -*/ - -static char otherside(opener) -char opener; -{ - switch (opener) { - case '(': - return(')'); - case '{': - return('}'); - case '[': - return(']'); - case '<': - return('>'); - } - -#ifdef DEBUG - abort(); -#endif -} - -int length_of_block(str) - string str; -{ - int len,temp; - char terminator; - - if ((! str[0])||(str[0]!='@')||((len=env_length(str+1)) == -1)) - return(-1); - - len++; - terminator=otherside(str[len++]); - do { - len+=((temp=length_of_block(str+len)) != -1)? - (temp): - (pure_text_length(str+len,terminator)); - } while (str[len] && str[len]!=terminator); - - return(str[len]?len+1:len); -} - -/* returns a character to close the most recently opened environment, - * or \0 if there are no open environments. - */ - -char close_bracket(str) - string str; -{ - int temp; - char ch,close; - - while (*str) { - if (temp=pure_text_length(str,0)) { - str+=temp; - } else { - temp = env_length(str+1)+2; - close = otherside(str[temp-1]); - if (ch=close_bracket(str+temp)) - return(ch); - temp = length_of_block(str); - if (str[temp-1] != close) - return(close); - else - str+=temp; - } - } - return('\0'); -} - string protect(str) string str; { string temp,temp2,temp3; - int len; - char ch; + int len,templen; + char_stack chs; + char tos; - /* verbatim all top-level strings */ + temp = string_Copy(""); + templen = 1; + chs = char_stack_create(); - temp=string_Copy(""); while(*str) { - if ((len=length_of_block(str)) == -1) { - temp2=string_CreateFromData(str,len=pure_text_length(str,0)); - str+=len; - temp3=verbatim(temp2); - temp=string_Concat2(temp,temp3); - free(temp3); + tos = (char_stack_empty(chs)?0:char_stack_top(chs)); + + if (*str == tos) { + /* if the character is the next terminator */ + + temp = (char *) realloc(temp,++templen); + temp[templen-2] = *str++; + char_stack_pop(chs); + temp[templen-1] = '\0'; + } else if (len = pure_text_length(str,tos)) { + if (tos) { + /* if the block is text in an environment, just copy it */ + + temp2 = string_CreateFromData(str,len); + str += len; + temp = string_Concat2(temp,temp2); + templen += len; + free(temp2); + } else { + /* if the block is top level text, verbatim it and add to temp */ + + temp2 = string_CreateFromData(str,len); + str += len; + temp3 = verbatim(temp2); + temp = string_Concat2(temp,temp3); + templen += strlen(temp3); + free(temp3); + } } else { - temp2=string_CreateFromData(str,len); - str+=len; - temp=string_Concat2(temp,temp2); + /* if the block is an environment, copy it, push delimiter */ + + len = env_length(str+1); + char_stack_push(chs,otherside(str[len+1])); + len += 2; + temp2 = string_CreateFromData(str,len); + str += len; + temp = string_Concat2(temp,temp2); + templen += len; free(temp2); } } - len=string_Length(temp)+1; /* len = size of malloc'd block */ - while ((ch=close_bracket(temp))>0) { - temp=(char *) realloc(temp,++len); - temp[len-2]=ch; - temp[len-1]='\0'; + /* all blocks have been copied. */ + + while (!char_stack_empty(chs)) { + temp = (char *) realloc(temp,++templen); + temp[templen-2] = char_stack_top(chs); + char_stack_pop(chs); } + temp[templen-1] = '\0'; return(temp); } -int not_contains(str, set) - string str; - character_class set; -{ - while (*str && ! set[*str]) str++; - return (! *str); -} - void free_desc(desc) desctype *desc; { |