/* * Diverses fonctions de base * (c)1991 par Denis GOUNELLE */ #include "aroff.h" #include "pile.h" static unsigned char tmp[1+LGMAXSTR<<1], aux[LGMAXSTR+1] ; extern struct Contexte *LastContext ; extern struct String *CurrentString ; extern unsigned char Arg[], OutputBuf[] ; extern char *ARoff_Version, *ARoff_Usage ; extern struct InputFile *CurrentInputFile ; extern struct Macro *CurrentMacro, *FindVar() ; extern struct TeteListe TReg, TStr, TMac, TTrp ; extern long ArgLen, OutputLen, TotalIndent, LineSpacing, LineNumber, NumInterv, NumSpace, NumIndent, PageOffset, Flg, TmpNoNum, InputMode, TmpIndent, OutputLine, PageLen, PageNumber, EmptyToWrite, NewPageNumber ; extern void do_ab(), do_ad(), do_am(), do_as(), do_bp(), do_br(), do_ce(), do_de(), do_ds(), do_el(), do_ex(), do_fi(), do_fs(), do_fl(), do_if(), do_in(), do_ll(), do_ls(), do_lt(), do_na(), do_ne(), do_nf(), do_nm(), do_nn(), do_nr(), do_pl(), do_pm(), do_pn(), do_po(), do_rm(), do_rr(), do_rs(), do_rt(), do_so(), do_sp(), do_ta(), do_tc(), do_ti(), do_tl(), do_tm(), do_tr(), do_ts(), do_wh() ; /**************************************************************************/ void Termine() { register long k ; register struct Macro *m ; CloseFile( CurrentInputFile ) ; VideListe( &TReg ) ; VideListe( &TStr ) ; VideListe( &TTrp ) ; for ( m = (struct Macro *)TMac.tl_Premier ; m ; m = (struct Macro *)m->m_Node.el_Suivant ) { VideListe( &(m->m_Def) ) ; for ( k = 0 ; m->m_Arg[k] ; k++ ) free( m->m_Arg[k] ) ; } VideListe( &TMac ) ; exit( 0 ) ; } /**************************************************************************/ void Abort( indic ) long indic ; { if ( (indic) && (OutputLen) ) { OutputBuf[OutputLen] = '\0' ; OutputLen = '\0' ; LigneSuiv( OutputBuf ) ; } Termine() ; } /**************************************************************************/ void FatalError( code , line , file ) long code, line ; char *file ; { if ( code == ERR_ARGS ) fprintf( stderr , "%s\n%s\n" , ARoff_Version , ARoff_Usage ) ; else { fprintf( stderr , "Error %d in file %s at line %d\n" , code , file , line ) ; if ( CurrentInputFile ) fprintf( stderr , "current file: %s, line: %d\n" , CurrentInputFile->if_Name , CurrentInputFile->if_Line ) ; } Abort( 0 ) ; } /**************************************************************************/ char *myalloc( len , indic ) register long len ; long indic ; { register long *p ; if (! len) Fatal( ERR_INTERNAL ) ; if ( len & 1 ) len++ ; /* forces len to next even value */ p = (long *)malloc( len ) ; if ( ! p ) Fatal( ERR_MEMORY ) ; if ( indic ) bzero( p , len ) ; return( (char *)p ) ; } /**************************************************************************/ void SetMacArgs() { register long k ; register struct Macro *m ; register unsigned char *p, c ; m = CurrentMacro ; m->m_NbArg = k = 0 ; while ( Arg[k] ) { p = m->m_Arg[m->m_NbArg] = (unsigned char *)myalloc( ArgLen - k + 1 , 0 ) ; while ( (c = Arg[k]) && (! isspace( c )) ) { if ( c == SC_FIXSPC ) c = ' ' ; *p = c ; k++ ; p++ ; } *p = '\0' ; while ( isspace( Arg[k] ) ) k++ ; m->m_NbArg++ ; } SetReg( ".$" , m->m_NbArg , 0 ) ; } /**************************************************************************/ struct Command CmdTable[] = { "ab",do_ab, "ad",do_ad, "am",do_am, "as",do_as, "bp",do_bp, "br",do_br, "ce",do_ce, "de",do_de, "ds",do_ds, "el",do_el, "ex",do_ex, "fi",do_fi, /*"fl",do_fl, inaccessible pour l'utilisateur */ "fs",do_fs, "if",do_if, "in",do_in, "ll",do_ll, "ls",do_ls, "lt",do_lt, "na",do_na, "ne",do_ne, "nf",do_nf, "nm",do_nm, "nn",do_nn, "nr",do_nr, "pl",do_pl, "pm",do_pm, "pn",do_pn, "po",do_po, "rm",do_rm, "rr",do_rr, "rs",do_rs, "rt",do_rt, "so",do_so, "sp",do_sp, "ta",do_ta, "tc",do_tc, "ti",do_ti, "tl",do_tl, "tm",do_tm, "tr",do_tr, "ts",do_ts, "wh",do_wh, "" ,NULL, } ; void ExecCmd( cmd ) char *cmd ; { register struct Macro *m ; register struct Command *p ; Arg[ArgLen] = '\0' ; /* est-ce une requete ? */ for ( p = CmdTable ; p->c_func ; p++ ) if (! strcmp( p->c_name , cmd )) { (*p->c_func)() ; goto _end ; } /* est-ce une macro ? */ m = FindVar( &TMac , cmd ) ; if ( m ) { if ( InputMode & IM_EXMACRO ) Push( TE_MACRO , CurrentMacro ) ; if ( InputMode & IM_STRING ) Push( TE_STRING , CurrentString ) ; Push( TE_INMODE , InputMode ) ; BCLR( InputMode , (IM_STRING|IM_EXMACRO) ) ; m->m_NextC = 0 ; m->m_NextL = (struct MLine *)m->m_Def.tl_Premier ; CurrentMacro = m ; SetMacArgs() ; BSET( InputMode , IM_EXMACRO ) ; } _end: if ( (Flg & F_WASIF) && (strcmp( cmd , "if")) ) BCLR( Flg , F_WASIF ) ; BCLR( Flg , F_NOBRK ) ; BSET( Flg , (F_MACREQ|F_WASNL) ) ; } /**************************************************************************/ long GetName( dst ) char *dst ; { long c ; if ( (c = GetChar()) == EOF ) return( 0 ) ; dst[0] = c ; if ( (c = GetChar()) == EOF ) return( 0 ) ; dst[1] = c ; dst[2] = '\0' ; return( 1 ) ; } /**************************************************************************/ long myatoi() { long k ; unsigned char *p ; k = strtol( Arg , &p , 10 ) ; if ( (*p != '\0') && (! isspace( *p )) ) Fatal( ERR_SYNTAX ) ; return( k ) ; } /**************************************************************************/ char *GetArg( pstr , pval ) unsigned char *pstr ; long *pval ; { while ( isspace( *pstr ) ) pstr++ ; if ( isdigit( *pstr ) ) *pval = atoi( pstr ) ; while ( (*pstr != '\0') && (! isspace( *pstr)) ) pstr++ ; return( pstr ) ; } /**************************************************************************/ long ChangeValue( val ) long *val ; { register char c ; register long k ; k = 0 ; c = '\0' ; if ( (Arg[k] == '+') || (Arg[k] == '-') ) { c = Arg[k] ; k++ ; } if (! isdigit( Arg[k] )) return( 0 ) ; k = atoi( &Arg[k] ) ; switch ( c ) { case '+' : *val += k ; break ; case '-' : *val -= k ; break ; default : *val = k ; break ; } return( 1 ) ; } /**************************************************************************/ void ChangePageNumber( number ) long number ; { PageNumber = number ; SetReg( "pn" , PageNumber , 0 ) ; NewPageNumber = number + 1 ; } /**************************************************************************/ long LigneSuiv( str ) char *str ; { register long k ; register char *p ; register struct Macro *m ; m = CurrentMacro ; k = strlen( str ) ; if ( TestTrp( OutputLine ) ) { BSET( Flg , F_TRAP ) ; BSET( CurrentMacro->m_Flag , MF_TRAP ) ; p = myalloc( k+1 , 0 ) ; strcpy( p , str ) ; Push( TE_OUTLINE , p ) ; Push( TE_TOWRITE , EmptyToWrite ) ; if ( m ) BSET( m->m_Flag , MF_WAIT ) ; EmptyToWrite = 0 ; return ; } if ( k ) do_fl( str ) ; OutputLine++ ; if ( OutputLine > PageLen ) { OutputLine = 1 ; ChangePageNumber( NewPageNumber ) ; } } /**************************************************************************/ void WriteLine() { register long k ; register unsigned char *p ; /* ajoute le decalage de page */ p = tmp ; for ( k = 0 ; k < PageOffset ; k++ , p++ ) *p = ' ' ; /* effectue la numerotation */ for ( k = 0 ; k < OutputLen ; k++ ) if (! isspace( OutputBuf[k] )) break ; if ( (Flg & F_NUMBER) && (k < OutputLen) && (! TmpNoNum) ) { for ( k = 0 ; k < NumIndent ; k++ , p++ ) *p = ' ' ; sprintf( aux , "%d" , LineNumber ) ; LineNumber++ ; SetReg( "ol" , LineNumber , 0 ) ; if ( (NumInterv != 1) && ((LineNumber % NumInterv) != 1) ) for ( k = 0 ; aux[k] != '\0' ; k++ ) aux[k] = ' ' ; strcpy( p , aux ) ; p += strlen( aux ) ; for ( k = 0 ; k < NumSpace ; k++ , p++ ) *p = ' ' ; } /* ajoute l'indentation */ for ( k = 0 ; k < TotalIndent ; k++ , p++ ) *p = ' ' ; if ( Flg & F_NOTI ) TmpIndent = 0 ; /* ecrit la ligne finale */ bcopy( OutputBuf , p , OutputLen ) ; p += OutputLen ; OutputLen = 0 ; *p = '\n' ; p[1] = '\0' ; EmptyToWrite += LineSpacing - 1 ; LigneSuiv( tmp ) ; } /**************************************************************************/ void SauveContexte( indic ) long indic ; { register long k ; register struct Macro *m ; register struct Contexte *p ; p = (struct Contexte *)myalloc( sizeof(struct Contexte) , 0 ) ; if ( InputMode & IM_EXMACRO ) { m = CurrentMacro ; bcopy( m , &(p->src.c_macro) , sizeof(struct Macro) ) ; p->c_ptr = (long)m ; p->c_len = sizeof(struct Macro) ; } else if ( InputMode & IM_STRING ) { k = 9 + CurrentString->s_len ; bcopy( CurrentString , &(p->src.c_string) , k ) ; p->c_ptr = (long)CurrentString ; p->c_len = k ; } else { bcopy( CurrentInputFile , &(p->src.c_file) , sizeof(struct InputFile) ) ; if (! (CurrentInputFile->if_Flag & IFF_LOADED)) { bcopy( CurrentInputFile->if_Buf , p->c_ibuf , CurrentInputFile->if_BufLen ) ; p->c_seek = lseek( p->src.c_file.if_Desc , 0 , 1 ) ; if ( p->c_seek == -1 ) Fatal( ERR_SEEK ) ; } p->c_ptr = (long)CurrentInputFile ; } bcopy( OutputBuf , p->c_obuf , OutputLen ) ; p->c_olen = OutputLen ; p->c_imod = InputMode ; p->c_flag = Flg ; if ( indic ) { if ( LastContext ) free( LastContext ) ; LastContext = p ; } else Push( TE_CONTEXT , p ) ; } /**************************************************************************/ void RestoreContexte( indic ) long indic ; { register struct Contexte *p ; if ( indic ) p = LastContext ; else p = (struct Contexte *) Pop( TE_CONTEXT , 1 ) ; Flg = p->c_flag ; InputMode = p->c_imod ; if ( InputMode & IM_EXMACRO ) { CurrentMacro = (struct Macro *)p->c_ptr ; bcopy( &(p->src.c_macro) , CurrentMacro , p->c_len ) ; } else if ( InputMode & IM_STRING ) { CurrentString = (struct String *)p->c_ptr ; bcopy( &(p->src.c_string) , CurrentString , p->c_len ) ; } else { CurrentInputFile = (struct InputFile *)p->c_ptr ; bcopy( &(p->src.c_file) , CurrentInputFile, sizeof(struct InputFile) ) ; if (! (CurrentInputFile->if_Flag & IFF_LOADED)) { bcopy( p->c_ibuf , CurrentInputFile->if_Buf , CurrentInputFile->if_BufLen ) ; if ( lseek( p->src.c_file.if_Desc , p->c_seek , 0 ) == -1 ) Fatal( ERR_SEEK ) ; } } bcopy( p->c_obuf , OutputBuf , OutputLen ) ; OutputLen = p->c_olen ; free( p ) ; if ( indic ) LastContext = NULL ; } /**************************************************************************/ void NewString( str ) char *str ; { register struct String *s ; if ( ! *str ) return ; if ( InputMode & IM_STRING ) Push( TE_STRING , CurrentString ) ; if ( InputMode & IM_EXMACRO ) Push( TE_MACRO , CurrentMacro ) ; Push( TE_INMODE , InputMode ) ; BCLR( InputMode , (IM_STRING|IM_EXMACRO) ) ; s = (struct String *)myalloc( sizeof(struct String) , 0 ) ; strcpy( s->s_val , str ) ; s->s_len = strlen( str ) ; s->s_pos = 0 ; CurrentString = s ; BSET( InputMode , IM_STRING ) ; } /**************************************************************************/ unsigned char *TestString( p ) register unsigned char *p ; { unsigned char *s, *d ; p++ ; if (! *p) Fatal( ERR_SYNTAX ) ; s = p ; while ( (*p != '\'') && (*p != '\0') ) p++ ; if ( *p != '\'' ) Fatal( ERR_SYNTAX ) ; *p = '\0' ; p++ ; if (! *p) Fatal( ERR_SYNTAX ) ; d = p ; while ( (*p != '\'') && (*p != '\0') ) p++ ; if ( *p != '\'' ) Fatal( ERR_SYNTAX ) ; *p = '\0' ; p++ ; if ( strcmp( s , d ) ) BSET( Flg , F_WASFALSE ) ; return( p ) ; } /**************************************************************************/ unsigned char *TestNum( p ) unsigned char *p ; { register char c ; register long s , d ; s = strtol( p , &p , 10 ) ; while ( isspace(*p) ) p++ ; if (! *p) Fatal( ERR_SYNTAX ) ; c = *p ; p++ ; while ( isspace(*p) ) p++ ; if (! *p) Fatal( ERR_SYNTAX ) ; d = strtol( p , &p , 10 ) ; switch ( c ) { case '<' : if ( s >= d ) BSET( Flg , F_WASFALSE ) ; break ; case '>' : if ( s <= d ) BSET( Flg , F_WASFALSE ) ; break ; case '=' : if ( s != d ) BSET( Flg , F_WASFALSE ) ; break ; default : Fatal( ERR_SYNTAX ) ; } return( p ) ; }