% Copyright (c): Marcel Roelofs and Peter Gragert
%                University of Twente, Enschede, The Netherlands
% @@(#) rweave.ch (91/03/11)

@x
    if (isdigit(c)) @<Get a constant@>@; /*spider*/
    else if (isalpha(c) || c=='_') @<Get an identifier@>@;/*spider*/
    else if (c=='\'' || c=='"') @<Get a string@>@;/*spider*/
@y
    if (isdigit(c)) @<Get a constant@>@;/*spider*/
    else if (isalpha(c) || c=='_' || c=='!') @<Get an identifier@>@;/*spider*/
    else if (c=='\"') @<Get a string@>@;/*spider*/
@z

@x
@ @<Get an identifier@>= {/*spider*/
  id_first=--loc;
  while (isalpha(*++loc) || isdigit(*loc) || *loc=='_');
  id_loc=loc; return(identifier);
}
@y
@ @<Get an identifier@>= {/*spider*/
  id_first=--loc;
  if (c=='!') ++loc;
  while (isalpha(*++loc) || isdigit(*loc) || *loc=='_' || *loc=='!') 
    if (*loc=='!') ++loc;
  id_loc=loc; return(identifier);
}
@z

@x
@ \cee\ strings and character constants, delimited by double and single
quotes, respectively, can contain newlines or instances of their own
delimiters if they are protected by a backslash.  We follow this
convention, but do not allow the string to be longer than |longest_name|.

@<Get a string@>= {/*spider*/
  ASCII delim = c; /* what started the string */
  id_first = mod_text+1;
  id_loc = mod_text;
  if (delim=='`' && *(loc-2)==at_sign) {
	/* make string begin with |"@@`"| */
	*++id_loc=at_sign; 
	*++id_loc=at_sign;
	}
	/* this is hack for ascii constant */
@#
/* if it's not a single-character literal, it's a tick mark or an |at_sign| */
  if ((delim=='\'' || delim == '`') && 
		(loc+1>=limit || 
			(*loc != '\\' && *loc!=at_sign && loc[1]!='\'')	|| 
			(*loc=='\\' && (loc+2>=limit||loc[2]!='\'')) ||
			(*loc==at_sign && 
			    (loc+2>=limit||loc[1]!=at_sign||loc[2]!='\''))
		)
      ) goto mistake;
  *++id_loc=delim;
  if (delim=='`') delim='\''; /* for |ascii_constant|s */
  while (1) {
    if (loc>=limit) {
      if(*(limit-1)!='\\') {
        err_print("! String didn't end"); loc=limit; break;
@.String didn't end@>
      }
      if(get_line()==0) {
        err_print("! Input ended in middle of string"); loc=buffer; break;
@.Input ended in middle of string@>
      }
    }
    if ((c=*loc++)==delim) {
      if (++id_loc<=mod_text_end) *id_loc=c;
      break;
    }
    if (c=='\\') if (loc>=limit) continue;
      else if (++id_loc<=mod_text_end) {
        *id_loc = '\\'; c=*loc++;
      }
    if (++id_loc<=mod_text_end) *id_loc=c;
  }
  if (id_loc>=mod_text_end) {
    printf("\n! String too long: ");
@.String too long@>
    ASCII_write(mod_text+1,25);
    printf("..."); mark_error;
  }
  id_loc++;
  return(string);
}
@y 
@ \cee\ strings are delimited by double quotes and must be restricted
to one line. Double quotes in strings must be doubled and we allow no
string to be longer than |longest_name|.

@<Get a string@>= {/*spider*/
  ASCII delim = c; /* what started the string */
@#
  id_first = mod_text+1;
  id_loc = mod_text; *++id_loc=delim;
  while (1) {
    if (loc>=limit) {
      err_print("! String didn't end"); loc=limit;
@.String didn't end@>
      if (get_line()==0) {
        err_print("! Input ended in middle of string"); loc=buffer;
@.Input ended in middle of string@>
      }
      break;
    }
    if ((c=*loc++)==delim) {
      if (++id_loc<=mod_text_end) *id_loc=c;
      if (*loc==delim) loc++;
      else break;
    }
    if (++id_loc<=mod_text_end) *id_loc=c;
  }
  if (id_loc>=mod_text_end) {
    printf("\n! String too long: ");
@.String too long@>
    ASCII_write(mod_text+1,25);
    printf("..."); mark_error;
  }
  id_loc++;
  return(string);
}
@z

@x
      case 1: printf("\\{"); print_id((name_dir+r)); printf("}"); break;
 /* |id_flag| */
      case 2: printf("\&{"); print_id((name_dir+r)); printf("}"); break;
@y
      case 1: printf("\\\\{"); print_id((name_dir+r)); printf("}"); break;
 /* |id_flag| */
      case 2: printf("\\&{"); print_id((name_dir+r)); printf("}"); break;
@z

@x
if (cur_xref->num%def_flag!=module_count) {
  app_str("+"); /*module name is multiply defined*/
  this_module=name_dir; /*so we won't give cross-reference info here*/
}
app_str("\\S"); /* output an equivalence sign */
@y
if (cur_xref->num%def_flag!=module_count) {
  app_str("\\PS"); /*module name is multiply defined*/
  this_module=name_dir; /*so we won't give cross-reference info here*/
}
else app_str("\\S"); /* output an equivalence sign */
@z