ftp.nice.ch/pub/next/text/framemaker/filters/la2mml.tar.gz#/auxprocs.c

This is auxprocs.c in view mode; [Download] [Up]

/* auxprocs.c */

/*
 * Copyright (c) 1991  R. Nigel Horspool.
 * All rights reserved.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

/* Auxiliary procedures called by GProc */

#include <stdio.h>
#include <ctype.h>
#ifdef THINK_C
#include <stdlib.h>
#endif
#include "tables.h"
#include "output.h"
#include "lexer.h"
#include "la2mml.h"
#include "auxprocs.h"

BOOL firstitem = TRUE;
BOOL filenameprinted = FALSE;

#ifndef THINK_C
/*  definitions for non-int external functions  */
extern char *malloc(), *strcpy(), *strcat();
#endif


static char *get_string_arg() {
    static char buff[MAXLEN+1];
    int i = 0;
    char delim = ' ';

    SKIPWSPACE();
    if (ch == '{') {
	delim = '}';  readch();
    }
    SKIPWSPACE();
    for( ; ; ) {
    	if (i < MAXLEN) buff[i++] = ch;
    	readch();
    	if ( isspace(ch) ||
    		ch == delim || ch == EOF )
    	    break;
    }
    if (delim != ' ') {
	SKIPWSPACE();
	if (ch != delim) {
	    LN();
	    FPR(stderr, "mismatched {\n" );		/* } */
	}
	readch();
    }
    buff[i] = '\0';
    if (i == 0) return NULL;
    return buff;
}


static ENVPTR get_environment() {
    char *s;
    s = get_string_arg();
    if (s == NULL) return &bad_env;
    return lookup_env( s );
}


/* handles \def command */
TOKEN DefProc( char *cmd ) {
    if (curr_matching_mode == MATH || curr_matching_mode == MATHARRAY) {
	LN();
	FPR(stderr, "\\def command used inside math mode\n" );
    }
    SKIPWSPACE();
    if (ch != '\\') {
	LN();
	FPR(stderr, "missing macro name after \\def\n" );
	return OTHER;
    }
    do {
	readch();
    } while( ch != '{' && ch != EOF );
    discard_output++;
    match_one_unit();
    discard_output--;
    return OTHER;
}


TOKEN VerbProc( char *dummy ) {
    register int delimiter;
    char *star = NULL;
    int ln = linenum;
    char *savefamily = nextfamily;
    short savefont = nextfont;
    
    if (ch == '*') {
	star = "*";
	readch();
    }

    delimiter = ch;
    if (isspace(delimiter)) {
	LN();
	FPR(stderr, "`\\verb%s' must not be followed by white space\n", star );
	goto EXIT;
    }
    readch();
    nextfamily = COURIERFAMILY;
    nextfont = PLAIN;
    while( ch != EOF ) {
	if (ch == '\n')
	    newline();
	else if (ch == ' ') {
	    if (star != NULL)
		copychar( '_' );	/* should be visible space char */
	    else
		appendstring( "\\x11  " );
	} else
	    copychar( ch );
	readch();
	if (ch == delimiter) {
	    readch();
	    goto EXIT;
	}
    }
    linenum = ln;
    LN();
    FPR(stderr, "unterminated \\verb%s construct\n", star );
EXIT:
    nextfamily = savefamily;
    nextfont = savefont;
    return OTHER;
}


TOKEN VSpaceProc( char *dummy ) {
    char buff[256], *cp;
    float val = 0.0;

    SKIPWSPACE();
    if (ch != '{')
	return GProc( "%x%n" );
    readch();
    SKIPWSPACE();
    if (isdigit(ch) || ch == '.') {
	for( cp=buff;  ; ) {
	    *cp++ = ch;
	    readch();
	    if (!isdigit(ch) && ch != '.') break;
	}
	*cp = '\0';
	sscanf(buff, "%f", &val );
	SKIPWSPACE();
	cp = buff;
	while( isalpha(ch) ) {
	    *cp++ = ch;
	    readch();
	}
	*cp = '\0';
	if (strcmp(buff,"in") == 0 || strcmp(buff,"truein") == 0)
	    val *= 72.0;
	else if (strcmp(buff,"cm") == 0)
	    val *= 28.35;
    }
    while( ch != '}' && ch != EOF )
	readch();
    readch();
    (void)sprintf(buff,
	"%%<FirstBody><SpaceBefore %2fpt> \\x09 %%n", val );
    GProc(buff);
    return OTHER;
}


TOKEN EnvProc( char *control ) {
    if (*control == '<') {
	char buffer[16], *bp;

	for( bp = buffer, control++;  *control != '>'; )
	    *bp++ = *control++;
	*bp = '\0';
	handle_environment( lookup_env(buffer), RBRACE );
    } else {
	ENVPTR env1, env2;
	int ln = linenum;

	env1 = get_environment();
	handle_environment( env1, ENDCMD );
	register_tag( curr_env->conttag );

	if (env1->kind != VERBATIM) {
	    env2 = get_environment();
	    if (env1 != env2) {
		LN();  FPR(stderr,
		    "closing env. name (%s) != opening name (%s) on line %d\n",
		    env2->name, env1->name, ln );
	    }
	}
    }
    return OTHER;
}


TOKEN MboxProc( char *dummy ) {
    ACTIONPTR meptr;
    TEXTMODE prev_mode = curr_matching_mode;
    char *savefamily = nextfamily;
    short savefont = nextfont;
    short savesize = nextsize;

    curr_matching_mode = PARA;
    nextfont = PLAIN;  nextfamily = TIMESFAMILY;
    meptr = get_token();
    if (GProc(meptr->code) == LBRACE)
	match_grouping( RBRACE );
    curr_matching_mode = prev_mode;
    nextfont = savefont;  nextfamily = savefamily;  nextsize = savesize;
    return OTHER;
}


TOKEN NewEnvProc( char *num ) {
    int n;
    n = atoi(num);
    while( n-- > 0 ) {
	skip_arg();
    }
    return OTHER;
}


TOKEN ItemProc( char *cmd ) {
    newline();
    GProc( cmd );
    if ( strcmp(curr_env->name, "enumerate") == 0 )
	register_tag( firstitem? "<1Step>" : "<Step>" );
    else if ( strcmp(curr_env->name, "itemize") == 0 )
	register_tag( "<Bullet>" ); 
    else
	register_tag( "<HangIndent>" );
    match_opt_arg();
    backup_white_space();
    appendstring( "\\t" );
    firstitem = FALSE;
    return OTHER;
}


TOKEN AccentProc( char *code ) {
    ACTIONPTR meptr;
    char c, base, *cp, buff[32];
    BOOL brace = FALSE, bad = FALSE;

    c = code[0];
    if (curr_env == tabbing_env &&
		(c == '=' || c == '`' || c == '\'')) {
	GProc( "%!" );
	return;
    }
    if (c == '?') {	/* \a form of command in tabbing environment */
	c = ch;  readch();
    }
    meptr = get_token();
    cp = meptr->cmd;
    if (cp[0] == '{' && cp[1] == '\0') {
	brace = TRUE;
	meptr = get_token();
    }
    if (meptr != &other) { bad = TRUE;  goto EXIT; }
    if (isalpha(tokenbuffer[0]) && tokenbuffer[1] == '\0')
	base = tokenbuffer[0];
    else if (strcmp(tokenbuffer,"\\imath") == 0) base = 'i';
    else if (strcmp(tokenbuffer,"\\jmath") == 0) base = 'j';
    else goto NOTRANS;
    for( meptr = accent_tab;  meptr->cmd != NULL;  meptr++ ) {
	if (meptr->cmd[0] == base && meptr->cmd[1] == c) {
	    GProc(meptr->code);
	    goto EXIT;
	}
    }
    /* no suitable translation found */
NOTRANS:
    (void)sprintf( buff, "%%fT\\\\%c{%s%%fT}%%f0", c, tokenbuffer ); 
    GProc( buff );
EXIT:
    if (brace) {
	meptr = get_token();
	cp = meptr->cmd;
	if (cp[0] != '}' || cp[1] != '\0')
	    bad = TRUE;
    }
    if (bad) {
	LN();  FPR(stderr, "bad use of accent command \\%c{..}\n", c );
    }
    return OTHER;
}


TOKEN CaptionProc( char *dummy ) {
    if ( strcmp(curr_env->name, "figure") == 0  ||
	 strcmp(curr_env->name, "figure*") == 0 )
	register_tag( "<Figure>" );
    else  /* we need some tag, so no point in further testing */
	register_tag( "<Table>" );
    match_one_unit();
    return OTHER;
}


TOKEN DelimiterProc( char *str ) {
    switch( str[0] ) {
    case '\\':
	switch( str[1] ) {
	case '[':		/* \[ command */
	    return LSQCMD;
	case ']':		/* \] command */
	    return RSQCMD;
	case '(':		/* \( command */
	    return LPARCMD;
	case ')':		/* \) command */
	    return RPARCMD;
	}
	break;
    case '[':
	return LSQ;
    case ']':
	return RSQ;
    case '{':		/* { command */
	return LBRACE;
    case '}':		/* } command */
	return RBRACE;
    case '$':		/* $ or $$ command */
	if (str[1] != '$')
	    return (curr_matching_mode == MATH)? DOLLAR_END : DOLLAR_START;
	else
	    return (curr_matching_mode ==MATH)? DOLLARDOLLAR_END : DOLLARDOLLAR_START;
    case 'e':		/* \end command */
	return ENDCMD;
    case 'E':		/* end-of-file */
	return EOFCMD;
    }
    return OTHER;
}


/*  Handles \input and \include commands.
    Note: the first argument is unused, it is provided in case
    we ever decide to support the \includeonly feature of LaTeX.  */
TOKEN ReadProc( char *cmd ) {
    char *s, *fn;
    int ln;
    FILE *saved_stream = f;
    BOOL saved_fnp = filenameprinted;

    s = get_string_arg();
    if (s == NULL) return OTHER;
    ln = strlen(s);
    /* check if filename has the .tex extension */
    if (ln <= 4 || strcmp( &(s[ln-4]), ".tex" ) != 0) {
	fn = malloc( (unsigned)(ln + 5) );
	MCHECK(fn);
	(void)strcpy( fn, s );
	(void)strcat( fn, ".tex" );
    } else {
	fn = malloc( (unsigned)(ln+1) );
	MCHECK(fn);
	(void)strcpy( fn, s );
    }
    ln = linenum;
    s = filename;
    filenameprinted = FALSE;
    (void)check_file( fn, fn );
    filename = s;
    f = saved_stream;
    linenum = ln;
    (void)free( fn );
    filenameprinted = (filenameprinted)? FALSE : saved_fnp;
    return OTHER;
}

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.