1476 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			1476 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			C
		
	
	
	
| /* chew
 | |
|    Copyright (C) 1990-1992 Free Software Foundation, Inc.
 | |
|    Contributed by steve chamberlain @cygnus
 | |
| 
 | |
| 
 | |
| This program is free software; you can redistribute it and/or modify
 | |
| it under the terms of the GNU General Public License as published by
 | |
| the Free Software Foundation; either version 2 of the License, or
 | |
| (at your option) any later version.
 | |
| 
 | |
| This program is distributed in the hope that it will be useful,
 | |
| but WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | |
| GNU General Public License for more details.
 | |
| 
 | |
| You should have received a copy of the GNU General Public License
 | |
| along with this program; if not, write to the Free Software
 | |
| Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 | |
| 
 | |
| /*
 | |
|  Yet another way of extracting documentation from source.
 | |
|  No, I haven't finished it yet, but I hope you people like it better
 | |
|  that the old way
 | |
|   
 | |
|  sac
 | |
| 
 | |
| Basically, this is a sort of string forth, maybe we should call it
 | |
| struth?
 | |
| 
 | |
| You define new words thus:
 | |
| : <newword> <oldwords> ;
 | |
| There is  no
 | |
| 
 | |
| */
 | |
| 
 | |
| 
 | |
| 
 | |
| #include "ansidecl.h"
 | |
| #include <stdio.h>
 | |
| #include <stdlib.h>
 | |
| #include <ctype.h>
 | |
| #include <string.h>
 | |
| 
 | |
| #define DEF_SIZE 5000
 | |
| #define STACK 50
 | |
| #define MIN_CMDLEN	4	/* Minimum length of a command */
 | |
| 
 | |
| int internal_wanted;
 | |
| int internal_mode;
 | |
| int Verbose=0;
 | |
| 
 | |
| 
 | |
| 
 | |
| /* Here is a string type ... */
 | |
| 
 | |
| typedef struct buffer 
 | |
| {
 | |
|     char *ptr;
 | |
|     unsigned int write_idx;
 | |
|     unsigned int size;
 | |
| } string_type;
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| static void DEFUN(init_string_with_size,(buffer, size),
 | |
| 	   string_type *buffer AND
 | |
| 	   unsigned int size )
 | |
| {
 | |
|   buffer->write_idx = 0;
 | |
|   buffer->size = size;
 | |
|   buffer->ptr = malloc(size);
 | |
| }
 | |
| 
 | |
| static void DEFUN(init_string,(buffer),
 | |
| 	   string_type *buffer)
 | |
| {
 | |
|     init_string_with_size(buffer, DEF_SIZE);
 | |
| 
 | |
| }
 | |
| 
 | |
| static int DEFUN(find, (str, what),
 | |
| 	  string_type *str AND
 | |
| 	  char *what)
 | |
| {
 | |
|     unsigned int i;
 | |
|     char *p;
 | |
|     p = what;
 | |
|     for (i = 0; i < str->write_idx && *p; i++) 
 | |
|     {
 | |
| 	if (*p == str->ptr[i])
 | |
| 	 p++;
 | |
| 	else
 | |
| 	 p = what;
 | |
|     }
 | |
|     return (*p == 0);
 | |
|     
 | |
| }
 | |
| 
 | |
| static void DEFUN(write_buffer,(buffer),
 | |
| 	   string_type *buffer)
 | |
| {
 | |
|     fwrite(buffer->ptr, buffer->write_idx, 1, stdout);
 | |
| }
 | |
| 
 | |
| 
 | |
| static void DEFUN(delete_string,(buffer),
 | |
| 	   string_type *buffer)
 | |
| {
 | |
|     free(buffer->ptr);
 | |
| }
 | |
| 
 | |
| 
 | |
| static char *DEFUN(addr, (buffer, idx),
 | |
| 	    string_type *buffer AND
 | |
| 	    unsigned int idx)
 | |
| {
 | |
|     return buffer->ptr + idx;
 | |
| }
 | |
| 
 | |
| static char DEFUN(at,(buffer, pos),
 | |
| 	   string_type *buffer AND
 | |
| 	   unsigned int pos) 
 | |
| {
 | |
|     if ( pos >= buffer->write_idx) 
 | |
|     {
 | |
| 	return 0;
 | |
|     }
 | |
|     return buffer->ptr[pos];
 | |
| }
 | |
| 
 | |
| static void DEFUN(catchar,(buffer, ch), 
 | |
| 	   string_type *buffer AND
 | |
| 	   char ch)
 | |
| {
 | |
|   if (buffer->write_idx == buffer->size) 
 | |
|   {
 | |
|     buffer->size *=2;
 | |
|     buffer->ptr = realloc(buffer->ptr, buffer->size);
 | |
|   }
 | |
| 
 | |
|   buffer->ptr[buffer->write_idx ++ ] = ch;
 | |
| }
 | |
| 
 | |
| 
 | |
| static void DEFUN(overwrite_string,(dst,   src),
 | |
| 	   string_type *dst AND
 | |
| 	   string_type *src)
 | |
| {
 | |
|     free(dst->ptr);
 | |
|     dst->size = src->size;
 | |
|     dst->write_idx = src->write_idx;
 | |
|     dst->ptr = src->ptr;
 | |
| }
 | |
| 
 | |
| static void DEFUN(catstr,(dst, src),
 | |
| 	   string_type *dst AND
 | |
| 	   string_type *src)
 | |
| {
 | |
|     unsigned int i;
 | |
|     for (i = 0; i < src->write_idx; i++) 
 | |
|     {
 | |
| 	catchar(dst, src->ptr[i]);
 | |
|     }
 | |
| }
 | |
| 
 | |
| 
 | |
| static void DEFUN(cattext,(buffer, string),
 | |
| 	   string_type *buffer AND
 | |
| 	   char *string)
 | |
| {
 | |
|     
 | |
|     while (*string) 
 | |
|     {
 | |
| 	catchar(buffer, *string);
 | |
| 	string++;
 | |
|     }
 | |
| }
 | |
| 
 | |
| static void DEFUN(catbuf,(buffer, buf, len),
 | |
| 	   string_type *buffer AND
 | |
| 	   char *buf AND
 | |
| 	   unsigned int len)
 | |
| {
 | |
|     
 | |
|     while (len--) 
 | |
|     {
 | |
| 	catchar(buffer, *buf);
 | |
| 	buf++;
 | |
|     }
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| static unsigned int 
 | |
| DEFUN(skip_white_and_stars,(src, idx),
 | |
|       string_type *src AND
 | |
|       unsigned int idx)
 | |
| {
 | |
|     while (isspace(at(src,idx)) 
 | |
| 	   || (at(src,idx) == '*' && at(src,idx +1) !='/')) 
 | |
|      idx++;
 | |
|     return idx;
 | |
|     
 | |
| 
 | |
| }
 | |
| /***********************************************************************/
 | |
| 
 | |
| 
 | |
| string_type stack[STACK];
 | |
| string_type *tos;
 | |
| 
 | |
| unsigned int idx = 0; /* Pos in input buffer */
 | |
| string_type *ptr; /* and the buffer */
 | |
| typedef void (*stinst_type)(NOARGS);
 | |
| stinst_type *pc;
 | |
| stinst_type sstack[STACK];
 | |
| stinst_type *ssp = &sstack[0];
 | |
| int istack[STACK];
 | |
| int *isp = &istack[0];
 | |
| 
 | |
| typedef int *word_type;
 | |
| 
 | |
| 
 | |
| 
 | |
| struct dict_struct
 | |
| {
 | |
|     char *word;
 | |
|     struct dict_struct *next;
 | |
|    stinst_type *code;
 | |
|     int code_length;
 | |
|     int code_end;
 | |
|     int var;
 | |
|     
 | |
| };
 | |
| typedef struct dict_struct dict_type;
 | |
| #define WORD(x) static void x(NOARGS)
 | |
| 
 | |
| static void DEFUN(exec,(word),
 | |
| 		  dict_type *word)
 | |
| {
 | |
|     pc = word->code;
 | |
|     while (*pc) 
 | |
|     {
 | |
| 	(*pc)();
 | |
|     }
 | |
|     
 | |
| }
 | |
| WORD(call)
 | |
| {
 | |
| stinst_type *oldpc = pc;
 | |
|     dict_type *e;
 | |
|     e =  (dict_type *)(pc [1]);
 | |
|     exec(e);
 | |
|     pc = oldpc + 2;
 | |
|     
 | |
| }
 | |
| 
 | |
| WORD(remchar)
 | |
| {
 | |
|     tos->write_idx--;    
 | |
|     pc++;
 | |
|     
 | |
| }
 | |
| 
 | |
| WORD(push_number)
 | |
| {
 | |
|     isp++;
 | |
|     pc++;
 | |
|     *isp = (int)(*pc);
 | |
|     pc++;
 | |
|     
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| WORD(push_text)
 | |
| {
 | |
|     
 | |
|     tos++;
 | |
|     init_string(tos);
 | |
|     pc++;
 | |
|     cattext(tos,*((char **)pc));
 | |
|     pc++;
 | |
|     
 | |
| }
 | |
| 
 | |
| 
 | |
|    
 | |
| /* This function removes everything not inside comments starting on
 | |
|    the first char of the line from the  string, also when copying
 | |
|    comments, removes blank space and leading *'s 
 | |
|    Blank lines are turned into one blank line
 | |
|  */
 | |
| 
 | |
| static void 
 | |
| DEFUN(remove_noncomments,(src,dst),
 | |
| 	   string_type *src AND
 | |
| 	   string_type *dst)
 | |
| {
 | |
|     unsigned int idx = 0;
 | |
|     
 | |
|     while (at(src,idx)) 
 | |
|     {
 | |
| 	/* Now see if we have a comment at the start of the line */
 | |
| 	if (at(src,idx) == '\n' 
 | |
| 	    && at(src,idx+1) ==  '/' 
 | |
| 	    && at(src,idx+2) == '*') 
 | |
| 	{
 | |
| 	    idx+=3;
 | |
| 	    
 | |
| 	    idx = skip_white_and_stars(src,idx);
 | |
| 
 | |
| 	    /* Remove leading dot */
 | |
| 	    if (at(src, idx) == '.')
 | |
| 	     idx++;
 | |
| 	    
 | |
| 	    /* Copy to the end of the line, or till the end of the
 | |
| 	       comment */
 | |
| 	    while (at(src, idx))
 | |
| 	    {
 | |
| 		if (at(src, idx) == '\n') 
 | |
| 		{
 | |
| 		    /* end of line, echo and scrape of leading blanks  */
 | |
| 		    if (at(src,idx +1) == '\n')
 | |
| 		     catchar(dst,'\n');
 | |
| 		    catchar(dst,'\n');
 | |
| 		    idx++;
 | |
| 		    idx =   skip_white_and_stars(src, idx);
 | |
| 		}
 | |
| 		else if (at(src, idx) == '*' && at(src,idx+1) == '/') 
 | |
| 		{
 | |
| 		    idx +=2 ;
 | |
| 		    cattext(dst,"\nENDDD\n");
 | |
| 		    break;
 | |
| 		}
 | |
| 		else 
 | |
| 		{
 | |
| 		    catchar(dst, at(src, idx));
 | |
| 		    idx++;
 | |
| 		}
 | |
| 	    }
 | |
| 	}
 | |
| 	else idx++;
 | |
|     }
 | |
| }
 | |
| /* turn foobar name(stuff); into foobar EXFUN(name,(stuff));
 | |
| 
 | |
|  */
 | |
| 
 | |
| static void
 | |
| DEFUN_VOID(exfunstuff)
 | |
| {
 | |
|     unsigned int openp;
 | |
|     unsigned int fname;
 | |
|     unsigned int idx;
 | |
|     string_type out;
 | |
|     init_string(&out);
 | |
|     
 | |
| 
 | |
|     /* make sure that it's not already exfuned */
 | |
|     if(find(tos,"EXFUN") || find(tos,"PROTO") || !find(tos,"(")) {
 | |
| 	    catstr(&out,tos);
 | |
| 	}
 | |
|     else 
 | |
|     {
 | |
| 	
 | |
| 	/*Find the open paren*/
 | |
| 	for (openp = 0; at(tos, openp) != '('  && at(tos,openp); openp++)
 | |
| 	 ;
 | |
| 
 | |
| 	fname = openp;
 | |
| 	/* Step back to the fname */
 | |
| 	fname--;
 | |
| 	while (fname && isspace(at(tos, fname)))
 | |
| 	 fname --;
 | |
| 	while (fname && !isspace(at(tos,fname)) && at(tos,fname) != '*')
 | |
| 	 fname--;
 | |
| 
 | |
| 	fname++;
 | |
| 	
 | |
| 	for (idx = 0; idx < fname; idx++) 
 | |
| 	{
 | |
| 	    catchar(&out, at(tos,idx));
 | |
| 	}
 | |
|     
 | |
| 	cattext(&out,"EXFUN(");
 | |
| 	for (idx = fname; idx < openp; idx++) 
 | |
| 	{
 | |
| 	    catchar(&out, at(tos,idx));
 | |
| 	}
 | |
| 	cattext(&out,", ");
 | |
| 	while (at(tos,idx) && at(tos,idx) !=';') 
 | |
| 	{
 | |
| 	    catchar(&out, at(tos, idx));
 | |
| 	    idx++;
 | |
| 	}
 | |
| 	cattext(&out,");\n");
 | |
|     }
 | |
|     overwrite_string(tos, &out);    
 | |
|     pc++;
 | |
|     
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| /* turn {*
 | |
|    and *} into comments */
 | |
| 
 | |
| WORD(translatecomments)
 | |
| {
 | |
|     unsigned int idx = 0;
 | |
|     string_type out;
 | |
|     init_string(&out);
 | |
|     
 | |
|     while (at(tos, idx)) 
 | |
|     {
 | |
| 	if (at(tos,idx) == '{' && at(tos,idx+1) =='*') 
 | |
| 	{
 | |
| 	    cattext(&out,"	/*");
 | |
| 	    idx+=2;
 | |
| 	}
 | |
| 	else if (at(tos,idx) == '*' && at(tos,idx+1) =='}') 
 | |
| 	{
 | |
| 	    cattext(&out,"*/");
 | |
| 	    idx+=2;
 | |
| 	}
 | |
| 	else  
 | |
| 	{
 | |
| 	    catchar(&out, at(tos, idx));
 | |
| 	    idx++;
 | |
| 	}
 | |
|     }
 | |
| 
 | |
| 
 | |
|     overwrite_string(tos, &out);
 | |
|     
 | |
|     pc++;
 | |
|     
 | |
| }
 | |
| 
 | |
| /* find something like
 | |
|    QUICKREF
 | |
|      memchar ansi  pure
 | |
| 
 | |
|      into
 | |
|      merge with words on tos and output them to stderror
 | |
| 
 | |
| */
 | |
| WORD(quickref)
 | |
| {
 | |
|   string_type *nos = tos-1;
 | |
|   unsigned int nosscan = 0;
 | |
|   unsigned int idx = 0;
 | |
|   
 | |
|   while (at(tos, idx)) 
 | |
|   {
 | |
|     if (at(tos,idx) == '~')
 | |
|     {
 | |
|       /* Skip the whitespace */
 | |
|       while (at(nos, nosscan) == ' ')
 | |
|        nosscan++;
 | |
|     
 | |
|       /* Sub the next word from the nos*/
 | |
|       while (at(nos, nosscan) != ' ' &&
 | |
| 	     at(nos, nosscan) != 0)
 | |
|       {
 | |
| 	fprintf(stderr, "%c", at(nos, nosscan));
 | |
| 	nosscan++;
 | |
|       }
 | |
|     }
 | |
|   
 | |
|     else 
 | |
|     {
 | |
|       fprintf(stderr,"%c", at(tos, idx));
 | |
|     
 | |
|     }
 | |
|     idx++;
 | |
|   }
 | |
| 
 | |
|   delete_string(tos);
 | |
|   delete_string(nos);
 | |
|   tos-=2;
 | |
|   pc++;
 | |
|   
 | |
| }
 | |
| 
 | |
| #if 0
 | |
| /* turn everything not starting with a . into a comment */
 | |
| 
 | |
| WORD(manglecomments)
 | |
| {
 | |
|     unsigned int idx = 0;
 | |
|     string_type out;
 | |
|     init_string(&out);
 | |
|     
 | |
|     while (at(tos, idx)) 
 | |
|     {
 | |
| 	if (at(tos,idx) == '\n' && at(tos,idx+1) =='*') 
 | |
| 	{
 | |
| 	    cattext(&out,"	/*");
 | |
| 	    idx+=2;
 | |
| 	}
 | |
| 	else if (at(tos,idx) == '*' && at(tos,idx+1) =='}') 
 | |
| 	{
 | |
| 	    cattext(&out,"*/");
 | |
| 	    idx+=2;
 | |
| 	}
 | |
| 	else  
 | |
| 	{
 | |
| 	    catchar(&out, at(tos, idx));
 | |
| 	    idx++;
 | |
| 	}
 | |
|     }
 | |
| 
 | |
| 
 | |
|     overwrite_string(tos, &out);
 | |
|     
 | |
|     pc++;
 | |
|     
 | |
| }
 | |
| #endif
 | |
| 
 | |
| /* Mod tos so that only lines with leading dots remain */
 | |
| static void
 | |
| DEFUN_VOID(outputdots)
 | |
| {
 | |
|     unsigned int idx = 0;
 | |
|     string_type out;
 | |
|     init_string(&out);
 | |
|     
 | |
|     while (at(tos, idx)) 
 | |
|     {
 | |
| 	if (at(tos, idx) == '\n' && at(tos, idx+1) == '.') 
 | |
| 	{
 | |
| 	    idx += 2;
 | |
| 	    
 | |
| 	    while (at(tos, idx) && at(tos, idx)!='\n')
 | |
| 	    {
 | |
| 		if (at(tos,idx) == '{' && at(tos,idx+1) =='*') 
 | |
| 		{
 | |
| 		    cattext(&out," /*");
 | |
| 		    idx+=2;
 | |
| 		}
 | |
| 		else if (at(tos,idx) == '*' && at(tos,idx+1) =='}') 
 | |
| 		{
 | |
| 		    cattext(&out,"*/");
 | |
| 		    idx+=2;
 | |
| 		}
 | |
| 		else  
 | |
| 		{
 | |
| 		    catchar(&out, at(tos, idx));
 | |
| 		    idx++;
 | |
| 		}
 | |
| 	    }
 | |
| 	    catchar(&out,'\n');
 | |
| 	}
 | |
| 	else 
 | |
| 	{
 | |
| 	    idx++;
 | |
| 	}
 | |
|     }	
 | |
| 
 | |
|     overwrite_string(tos, &out);
 | |
|     pc++;
 | |
|     
 | |
| }
 | |
| 
 | |
| /* Find lines starting with . and | and put example around them on tos
 | |
|    turn 
 | |
|    {*  into open comment and *} into close comment
 | |
|    escape curlies
 | |
|    
 | |
| */
 | |
| WORD(courierize)
 | |
| {
 | |
|     string_type out;
 | |
|     unsigned int idx = 0;
 | |
|     
 | |
|     init_string(&out);
 | |
|     
 | |
|     while (at(tos, idx)) 
 | |
|     {
 | |
| 	if (at(tos, idx) == '\n' 
 | |
| 	    && (at(tos, idx +1 ) == '.'
 | |
| 		|| at(tos,idx+1) == '|')) 
 | |
| 	{
 | |
| 	    cattext(&out,"\n@smallexample\n");
 | |
| 	    do 
 | |
| 	    {
 | |
| 		idx += 2;
 | |
| 		
 | |
| 		while (at(tos, idx) && at(tos, idx)!='\n')
 | |
| 		{
 | |
| 		    if (at(tos,idx)=='{' && at(tos,idx+1) =='*') 
 | |
| 		    {
 | |
| 			cattext(&out," /*");
 | |
| 			idx+=2;
 | |
| 		    }
 | |
| 		    else if (at(tos,idx)=='*' && at(tos,idx+1) =='}') 
 | |
| 		    {
 | |
| 			cattext(&out,"*/");
 | |
| 			idx+=2;
 | |
| 		    }
 | |
| 	            else if (at(tos,idx) == '{')
 | |
| 		    {
 | |
| 			cattext(&out,"@{");
 | |
| 			idx++;
 | |
| 		    }
 | |
| 	            else if (at(tos,idx) == '}')
 | |
| 		    {
 | |
| 			cattext(&out,"@}");
 | |
| 			idx++;
 | |
| 		    }
 | |
| 		    else 
 | |
| 		    {
 | |
| 			catchar(&out, at(tos, idx));
 | |
| 			idx++;
 | |
| 		    }
 | |
| 		    
 | |
| 		}
 | |
| 		catchar(&out,'\n');
 | |
| 	    }  
 | |
| 	    while (at(tos, idx) == '\n' 
 | |
| 		   && (at(tos, idx+1) == '.')
 | |
| 		   || (at(tos,idx+1) == '|'));
 | |
| 	    cattext(&out,"@end smallexample");
 | |
| 	}
 | |
| 	else 
 | |
| 	{    
 | |
| 	    catchar(&out, at(tos, idx));
 | |
| 	    idx++;
 | |
| 	}
 | |
|     }    
 | |
| 
 | |
|     overwrite_string(tos, &out);
 | |
|     pc++;
 | |
| 
 | |
|     
 | |
| }
 | |
| 
 | |
| /* 
 | |
| bulletize:  look for bullet item commands at start of line
 | |
|  Bullet list:
 | |
|    O+  emit @itemize @bullet
 | |
|    o   emit @item	[note lowercase]
 | |
|    O-  emit @end itemize
 | |
| 
 | |
|  Variable label list:
 | |
|    o+  emit @table @code
 | |
|    o   emit @item
 | |
|    o-  emit @end table
 | |
| */
 | |
| 
 | |
| 
 | |
| WORD(bulletize)
 | |
| {
 | |
|   unsigned int idx = 0;
 | |
|   string_type out;
 | |
|   init_string(&out);
 | |
|     
 | |
|   while (at(tos, idx)) {
 | |
|        if (at(tos, idx) == '\n' &&  at(tos, idx+1) == 'o')
 | |
|        {
 | |
| 	 if (at(tos,idx+2) == '+') {
 | |
| 	     cattext(&out,"\n@table @code\n");
 | |
| 	     idx+=3;
 | |
| 	   }
 | |
| 	 else if (at(tos,idx+2) == '-') {
 | |
| 	     cattext(&out,"\n@end table\n");
 | |
| 	     idx+=3;
 | |
| 	   }
 | |
| 	 else if (isspace(at(tos,idx+2))) {
 | |
| 	     cattext(&out,"\n@item ");
 | |
| 	     idx+=3;
 | |
| 	   }
 | |
| 	 else {
 | |
| 	     catchar(&out, at(tos, idx));
 | |
| 	     idx++;
 | |
| 	   }
 | |
|        }
 | |
|       
 | |
|        else
 | |
| 	if (at(tos, idx) == '\n' &&  at(tos, idx+1) == 'O')
 | |
| 	{
 | |
| 	  if (at(tos,idx+2) == '+') {
 | |
| 	      cattext(&out,"\n@itemize @bullet\n");
 | |
| 	      idx+=3;
 | |
| 	    }
 | |
| 
 | |
| 	  else if (at(tos,idx+2) == '-') {
 | |
| 	      cattext(&out,"\n@end itemize\n");
 | |
| 	      idx+=3;
 | |
| 	    }
 | |
| 	  else {
 | |
| 	      catchar(&out, at(tos, idx));
 | |
| 	      idx++;
 | |
| 	    }
 | |
| 	}	      
 | |
| 	else
 | |
| 	{
 | |
| 	  catchar(&out, at(tos, idx));
 | |
| 	  idx++;
 | |
| 	}
 | |
|     }
 | |
| 
 | |
|   delete_string(tos);
 | |
|   *tos = out;
 | |
|   pc++;
 | |
|     
 | |
| }
 | |
| 
 | |
| /* Turn <<foo>> into @code{foo} in place at TOS 
 | |
|    Turn <[foo]> into @var{foo} in place at TOS
 | |
|    nest them too !
 | |
| 
 | |
| */
 | |
|    
 | |
| 
 | |
| WORD(do_fancy_stuff)
 | |
|  {
 | |
|     unsigned int idx = 0;
 | |
|     string_type out;
 | |
|     init_string(&out);
 | |
|     while (at(tos, idx)) 
 | |
|     {
 | |
| 	if (at(tos, idx) == '<' 
 | |
| 	    && at(tos, idx+1) == '<'
 | |
| 	    && (!isspace(at(tos,idx + 2)) || at(tos,idx+3) == '>')) 
 | |
| 	{
 | |
| 	    /* This qualifies as a << startup */
 | |
| 	    idx +=2;
 | |
| 	    cattext(&out,"@code{");
 | |
| 	  }
 | |
| 	
 | |
| 	else 	if (at(tos, idx) == '<' 
 | |
| 	    && at(tos, idx+1) == '['
 | |
| 	    && !isspace(at(tos,idx + 2))) 
 | |
| 	{
 | |
| 	    /* This qualifies as a <[ startup */
 | |
| 	    idx +=2;
 | |
| 	    cattext(&out,"@var{");
 | |
| 	  }
 | |
| 	else if (at(tos, idx) == '>' 
 | |
| 		 && at(tos,idx+1) =='>') 
 | |
| 	{
 | |
| 	  
 | |
| 	    cattext(&out,"}");
 | |
| 	    idx+=2;
 | |
| 	}
 | |
| 	else if (at(tos, idx) == ']' 
 | |
| 		 && at(tos,idx+1) =='>') 
 | |
| 	{
 | |
| 	    cattext(&out,"}");
 | |
| 	    idx+=2;
 | |
| 	}
 | |
| 	else 
 | |
| 	{
 | |
| 	    catchar(&out, at(tos, idx));
 | |
| 	    idx++;
 | |
| 	}
 | |
|     }
 | |
|     delete_string(tos);
 | |
|     *tos = out;
 | |
|     pc++;
 | |
|     
 | |
| }
 | |
| /* A command is all upper case,and alone on a line */
 | |
| static int 
 | |
| DEFUN( iscommand,(ptr, idx),
 | |
|       string_type *ptr AND
 | |
|       unsigned int idx)
 | |
| {
 | |
|     unsigned int len = 0;
 | |
|     while (at(ptr,idx)) {
 | |
| 	    if (isupper(at(ptr,idx)) || at(ptr,idx) == ' ' ||
 | |
| 		at(ptr,idx) == '_') 
 | |
| 	    {
 | |
| 	     len++;
 | |
| 	     idx++;
 | |
| 	 }
 | |
| 	    else if(at(ptr,idx) == '\n')
 | |
| 	    {
 | |
| 		/* The length check will never fail on a real command
 | |
| 		 * because the commands are screened as the definitions file
 | |
| 		 * is read.  */
 | |
| 		if (len >= MIN_CMDLEN) return 1;
 | |
| 		return 0;
 | |
| 	    }
 | |
| 	    else return 0;
 | |
| 	}
 | |
|     return 0;
 | |
| 
 | |
| }
 | |
| 
 | |
| 
 | |
| unsigned int
 | |
| DEFUN(copy_past_newline,(ptr, idx, dst),
 | |
|       string_type *ptr AND
 | |
|       unsigned int idx AND
 | |
|       string_type *dst)
 | |
| {
 | |
|     while (at(ptr, idx) && at(ptr, idx) != '\n') 
 | |
|     {
 | |
| 	catchar(dst, at(ptr, idx));
 | |
| 	idx++;
 | |
| 	
 | |
|     }    
 | |
|     catchar(dst, at(ptr, idx));
 | |
|     idx++;
 | |
|     return idx;
 | |
| 
 | |
| }
 | |
| 
 | |
| WORD(icopy_past_newline)
 | |
| {
 | |
|     tos++;
 | |
|     init_string(tos);
 | |
|     idx = copy_past_newline(ptr, idx, tos);
 | |
|     pc++;	
 | |
| }
 | |
| 
 | |
| 
 | |
| /* indent
 | |
|    Take the string at the top of the stack, do some prettying */
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| WORD(kill_bogus_lines)
 | |
| {
 | |
|     int sl ;
 | |
|     
 | |
|     int idx = 0;
 | |
|     int c;
 | |
|     int dot = 0    ;
 | |
|     
 | |
|     string_type out;    
 | |
|     init_string(&out);
 | |
|     /* Drop leading nl */
 | |
|     while (at(tos,idx) == '\n')
 | |
|     {
 | |
| 	idx++;
 | |
|     }
 | |
|     c = idx;
 | |
|     
 | |
|     /* Find the last char */
 | |
|     while (at(tos,idx))
 | |
|     {
 | |
| 	idx++;
 | |
|     }
 | |
|     
 | |
|     /* find the last non white before the nl */
 | |
|     idx--;
 | |
|     
 | |
|     while (idx && isspace(at(tos,idx)))
 | |
|      idx--;
 | |
|     idx++;
 | |
|     
 | |
|     /* Copy buffer upto last char, but blank lines before and after
 | |
|        dots don't count */
 | |
|     sl = 1;
 | |
| 
 | |
|     while (c < idx)
 | |
|     {
 | |
| 	if (at(tos,c) == '\n' 
 | |
| 	    && at(tos,c+1) == '\n'
 | |
| 	    && at(tos,c+2) == '.') 
 | |
| 	{
 | |
| 	    /* Ignore two linelines before  a dot*/
 | |
| 	    c++;
 | |
| 	}
 | |
| 	else if (at(tos,c) == '.' && sl)
 | |
| 	{
 | |
| 	    /* remember that this line started with a dot */
 | |
| 	    dot=2;
 | |
| 	}
 | |
| 	else if (at(tos,c) == '\n' 
 | |
| 		 && at(tos,c+1) == '\n'
 | |
| 		 && dot)
 | |
| 	{
 | |
| 	    c++;
 | |
| 	    /* Ignore two newlines when last line was dot */
 | |
| 	}
 | |
| 
 | |
| 	catchar(&out, at(tos,c));
 | |
| 	if (at(tos,c) == '\n')
 | |
| 	{
 | |
| 	    sl = 1;
 | |
| 	    
 | |
| 	    if (dot == 2)dot=1;else dot = 0;
 | |
| 	}
 | |
| 	
 | |
| 	c++;	
 | |
| 
 | |
|     }
 | |
|     
 | |
|     /* Append nl*/
 | |
|     catchar(&out, '\n');
 | |
|     pc++;
 | |
|     delete_string(tos);
 | |
|     *tos = out;
 | |
|     
 | |
|     
 | |
| }
 | |
| 
 | |
| WORD(indent)
 | |
| {
 | |
|     string_type out;
 | |
|     int tab = 0;
 | |
|     int idx = 0;
 | |
|     int ol =0;
 | |
|     init_string(&out);
 | |
|     while (at(tos,idx)) {
 | |
| 	    switch (at(tos,idx)) 
 | |
| 	    {
 | |
| 	      case '\n':
 | |
| 		cattext(&out,"\n");
 | |
| 		idx++;
 | |
| 		if (tab) 
 | |
| 		{
 | |
| 		    cattext(&out,"    ");
 | |
| 		}
 | |
| 		ol = 0;
 | |
| 		break;
 | |
| 	      case '(':
 | |
| 		tab++;
 | |
| 		if (ol == 0)
 | |
| 		    cattext(&out,"   ");
 | |
| 		idx++;
 | |
| 		cattext(&out,"(");
 | |
| 		ol = 1;
 | |
| 		break;
 | |
| 	      case ')':
 | |
| 		tab--;
 | |
| 		cattext(&out,")");
 | |
| 		idx++;
 | |
| 		ol=1;
 | |
| 		
 | |
| 		break;
 | |
| 	      default:
 | |
| 		catchar(&out,at(tos,idx));
 | |
| 		ol=1;
 | |
| 		
 | |
| 		idx++;
 | |
| 		break;
 | |
| 	    }
 | |
| 	}	
 | |
| 
 | |
|     pc++;
 | |
|     delete_string(tos);
 | |
|     *tos = out;
 | |
| 
 | |
| }
 | |
| 
 | |
| /* Change the TOS so that all that is left is the stuff inside the
 | |
|  first <<foo>> .
 | |
| */
 | |
| 
 | |
| WORD(get_stuff_in_angle)
 | |
| {
 | |
|   unsigned int idx = 0;
 | |
|   string_type out;
 | |
|   init_string(&out);
 | |
|     
 | |
|   while (at(tos, idx)) 
 | |
|     {
 | |
|       if (at(tos,idx) == '<' && at(tos,idx+1) =='<') 
 | |
| 	{
 | |
| 	  idx+=2;
 | |
| 	  
 | |
| 	  while (!(at(tos,idx) == '>' && at(tos,idx+1) == '>'))
 | |
| 	    {
 | |
| 	      catchar(&out, at(tos, idx));
 | |
| 	      idx++;
 | |
| 	    }
 | |
| 	  break;
 | |
| 	}
 | |
|       idx++;
 | |
|     }
 | |
|   catchar(&out,'\n');
 | |
|   
 | |
|   overwrite_string(tos, &out);
 | |
|   pc++;
 | |
| }
 | |
| 
 | |
| 
 | |
| WORD(get_stuff_in_command)
 | |
| {
 | |
|   tos++;
 | |
|   init_string(tos);
 | |
| 
 | |
|   while (at(ptr, idx)) {
 | |
|     if (iscommand(ptr, idx))  break;
 | |
|     idx =   copy_past_newline(ptr, idx, tos);
 | |
|   }
 | |
|   pc++;    
 | |
| }
 | |
| 
 | |
| WORD(swap)
 | |
| {
 | |
|     string_type t;
 | |
|     
 | |
|     t = tos[0];
 | |
|     tos[0] = tos[-1];
 | |
|     tos[-1] =t; 
 | |
|     pc++;
 | |
|     
 | |
| }
 | |
| 
 | |
| WORD(dup)
 | |
| {
 | |
|     tos++;
 | |
|     init_string(tos);
 | |
|     catstr(tos, tos-1);
 | |
|     pc++;
 | |
|     
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| WORD(icatstr)
 | |
| {
 | |
|     catstr(tos-1, tos);
 | |
|     delete_string(tos);
 | |
|     tos--;
 | |
|     pc++;
 | |
|     
 | |
| }
 | |
| 
 | |
| WORD(skip_past_newline)
 | |
| {
 | |
|     while (at(ptr,idx) 
 | |
| 	   && at(ptr,idx) != '\n')
 | |
|      idx++;
 | |
|     idx++;
 | |
|     pc++;
 | |
| }
 | |
| 
 | |
| 
 | |
| WORD(internalmode)
 | |
| {
 | |
|     internal_mode = *(isp);
 | |
|     isp--;
 | |
|     pc++;
 | |
| }
 | |
| 
 | |
| WORD(maybecatstr)
 | |
| {
 | |
|     if (internal_wanted == internal_mode) 
 | |
|     {
 | |
| 	catstr(tos-1, tos);
 | |
|     }
 | |
|     delete_string(tos);
 | |
|     tos--;
 | |
|     pc++;
 | |
|     
 | |
| }
 | |
| 
 | |
| char *
 | |
| DEFUN(nextword,(string, word),
 | |
|       char *string AND
 | |
|       char **word)
 | |
| {
 | |
|   char *word_start;
 | |
|   int idx;
 | |
|   char *dst;
 | |
|   char *src;
 | |
|     
 | |
|   int length = 0;
 | |
|     
 | |
|   while (isspace(*string) || *string == '-') {
 | |
|       if (*string == '-') 
 | |
|       {
 | |
| 	while (*string && *string != '\n') 
 | |
| 	 string++;
 | |
| 		
 | |
|       }
 | |
|       else {
 | |
| 	  string++;
 | |
| 	}
 | |
|     }
 | |
|   if (!*string) return 0;
 | |
|     
 | |
|   word_start = string;    	
 | |
|   if (*string == '"') 
 | |
|   {
 | |
|     string++;
 | |
|     length++;
 | |
| 	
 | |
|     while (*string != '"') 
 | |
|     {
 | |
|       string++;
 | |
|       length++;
 | |
|     }
 | |
|   }
 | |
|   else     
 | |
|   {
 | |
| 	
 | |
| 
 | |
|     while (!isspace(*string)) 
 | |
|     {
 | |
|       string++;
 | |
|       length++;
 | |
|     }
 | |
|   }
 | |
|     
 | |
|   *word = malloc(length + 1);
 | |
| 
 | |
|   dst = *word;
 | |
|   src = word_start;
 | |
| 
 | |
| 
 | |
|   for (idx= 0; idx < length; idx++) 
 | |
|   {
 | |
|     
 | |
|     if (src[idx] == '\\' && src[idx+1] == 'n') 
 | |
|     {
 | |
|       *dst++ = '\n';
 | |
|       idx++;
 | |
|     
 | |
|     }
 | |
|     else *dst++ = src[idx];
 | |
|   }
 | |
|   *dst++ = 0;
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
|   if(*string)    
 | |
|    return string + 1;
 | |
|   else 
 | |
|    return 0;
 | |
|     
 | |
| }
 | |
| dict_type *root;
 | |
| dict_type *
 | |
| DEFUN(lookup_word,(word),
 | |
|       char *word)
 | |
| {
 | |
|     dict_type *ptr = root;
 | |
|     while (ptr) {
 | |
| 	    if (strcmp(ptr->word, word) == 0) return ptr;
 | |
| 	    ptr = ptr->next;
 | |
| 	    
 | |
| 	 }
 | |
|     fprintf(stderr,"Can't find %s\n",word);
 | |
|     return 0;
 | |
|     
 | |
|     
 | |
| }
 | |
| 
 | |
| static void DEFUN_VOID(perform)
 | |
| {
 | |
|     tos = stack;
 | |
|     
 | |
|     while (at(ptr, idx)) {
 | |
| 	    /* It's worth looking through the command list */
 | |
| 	    if (iscommand(ptr, idx))
 | |
| 	    {
 | |
| 		char *next;
 | |
| 		dict_type *word ;
 | |
| 		
 | |
| 		(void)		nextword(addr(ptr, idx), &next);
 | |
| 
 | |
| 
 | |
| 		word = lookup_word(next);
 | |
| 
 | |
| 
 | |
| 		
 | |
| 
 | |
| 		if (word) 
 | |
| 		{
 | |
| 		    if(Verbose)  fprintf(stderr, "CMD '%s'\n", word->word);
 | |
| 		    exec(word);
 | |
| 		}
 | |
| 		else
 | |
| 		{
 | |
| 		    fprintf(stderr,"warning, %s is not recognised\n",  next);
 | |
| 		    skip_past_newline();
 | |
| 		}
 | |
| 		
 | |
| 	    }
 | |
| 	    else skip_past_newline();
 | |
| 
 | |
| 	}
 | |
| }
 | |
| 
 | |
| dict_type *
 | |
| DEFUN(newentry,(word),
 | |
|       char *word)
 | |
| {
 | |
|     dict_type *new = (dict_type *)malloc(sizeof(dict_type));
 | |
|     new->word = word;
 | |
|     new->next = root;
 | |
|     root = new;
 | |
|     new->code = (stinst_type *)malloc(sizeof(stinst_type ));
 | |
|     new->code_length = 1;
 | |
|     new->code_end = 0;
 | |
|     return new;
 | |
|     
 | |
| }
 | |
| 
 | |
| 
 | |
| unsigned int
 | |
| DEFUN(add_to_definition,(entry, word), 
 | |
|       dict_type *entry AND
 | |
|       stinst_type word)
 | |
| {
 | |
|     if (entry->code_end == entry->code_length) 
 | |
|     {
 | |
| 	entry->code_length += 2;
 | |
| 	entry->code =
 | |
| 	 (stinst_type *) realloc((char *)(entry->code),
 | |
| 			       entry->code_length *sizeof(word_type));
 | |
|     }
 | |
|     entry->code[entry->code_end] = word;
 | |
|     
 | |
| return     entry->code_end++;  
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| void
 | |
| DEFUN(add_intrinsic,(name, func),
 | |
|       char *name AND
 | |
|       void (*func)(NOARGS))
 | |
| {
 | |
|     dict_type *new = newentry(name);
 | |
|     add_to_definition(new, func);
 | |
|     add_to_definition(new, 0);
 | |
| }
 | |
| 
 | |
| void
 | |
| DEFUN(add_var,(name),
 | |
|       char *name)
 | |
| {
 | |
|     dict_type *new = newentry(name);
 | |
|     add_to_definition(new, push_number);
 | |
|     add_to_definition(new, (stinst_type)(&(new->var)));
 | |
|     add_to_definition(new,0);
 | |
|     
 | |
| }
 | |
|       
 | |
| 
 | |
| 
 | |
| 
 | |
| int
 | |
| DEFUN(compile, (string), 
 | |
|       char *string)
 | |
| 
 | |
| {
 | |
|     int  ret=0;
 | |
|     /* add words to the dictionary */
 | |
|     char *word;
 | |
|     string = nextword(string, &word);
 | |
|     while (string && *string && word[0]) 
 | |
|     {
 | |
| 	if (strcmp(word,"var")==0) 
 | |
| 	{
 | |
| 	  string=nextword(string, &word);
 | |
| 	  
 | |
| 	  add_var(word);
 | |
| 	  string=nextword(string, &word);
 | |
| 	}
 | |
| 	else	
 | |
| 	    
 | |
| 	if (word[0] == ':')
 | |
| 	{
 | |
| 	    dict_type *ptr;
 | |
| 	    /* Compile a word and add to dictionary */
 | |
| 	    string = nextword(string, &word);
 | |
| 	    if(Verbose)  fprintf(stderr, "Found command '%s'\n", word);
 | |
| 	    if(strlen(word) < MIN_CMDLEN)  {
 | |
| 		fprintf(stderr, "ERROR:  Command '%s' is too short ", word);
 | |
| 		fprintf(stderr, "(MIN_CMDLEN is %d)\n", MIN_CMDLEN);
 | |
| 		ret++;
 | |
| 	    }
 | |
| 	    
 | |
| 	    ptr = newentry(word);
 | |
| 	    string = nextword(string, &word);
 | |
| 	    while (word[0] != ';' ) 
 | |
| 	    {
 | |
| 		 switch (word[0]) 
 | |
| 		 {
 | |
| 		    
 | |
| 		    
 | |
| 		   case '"':
 | |
| 		     /* got a string, embed magic push string
 | |
| 			function */
 | |
| 		     add_to_definition(ptr, push_text);
 | |
| 		     add_to_definition(ptr, (stinst_type)(word+1));
 | |
| 		     break;
 | |
| 		   case '0':
 | |
| 		   case '1':
 | |
| 		   case '2':
 | |
| 		   case '3':
 | |
| 		   case '4':
 | |
| 		   case '5':
 | |
| 		   case '6':
 | |
| 		   case '7':
 | |
| 		   case '8':
 | |
| 		   case '9':
 | |
| 		     /* Got a number, embedd the magic push number
 | |
| 			function */
 | |
| 		     add_to_definition(ptr, push_number);
 | |
| 		     add_to_definition(ptr, atol(word));
 | |
| 		     break;
 | |
| 		   default:
 | |
| 		     add_to_definition(ptr, call);
 | |
| 		     add_to_definition(ptr, lookup_word(word));
 | |
| 		 }
 | |
| 
 | |
| 		string = nextword(string, &word);		     
 | |
| 	    }
 | |
| 	    add_to_definition(ptr,0);
 | |
| 	    string = nextword(string, &word);
 | |
| 	}
 | |
| 	else 
 | |
| 	{
 | |
| 	    fprintf(stderr,"syntax error at %s\n",string-1);
 | |
| 	    ret++;
 | |
| 	}	    
 | |
|     }
 | |
| 
 | |
| return(ret);
 | |
| }
 | |
| 
 | |
|  
 | |
| static void DEFUN_VOID(bang)
 | |
| {
 | |
| *(int *)((isp[0])) = isp[-1];
 | |
| isp-=2;
 | |
| pc++;
 | |
| 
 | |
| }
 | |
| 
 | |
| WORD(atsign)
 | |
| {
 | |
|     isp[0] = *(int *)(isp[0]);
 | |
|     pc++;
 | |
| }
 | |
| 
 | |
| WORD(hello)
 | |
| {
 | |
|     
 | |
|     printf("hello\n");
 | |
|     pc++;    
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| static void DEFUN(read_in, (str, file), 
 | |
| 	   string_type *str AND
 | |
| 		  FILE *file)
 | |
| {
 | |
|     char buff[10000];    
 | |
|     unsigned int r;
 | |
|     do 
 | |
|     {
 | |
| 	r = fread(buff, 1, sizeof(buff), file);
 | |
| 	catbuf(str, buff, r);
 | |
|     }
 | |
|     while (r);
 | |
|     buff[0] = 0;
 | |
|     
 | |
|     catbuf(str, buff,1);
 | |
|     
 | |
| }
 | |
| 
 | |
| 
 | |
| #if 0
 | |
| static void DEFUN_VOID(usage)
 | |
| {
 | |
|     fprintf(stderr,"usage: -[i|v] -f macrofile <file >file\n");
 | |
|     exit(33);    
 | |
| }
 | |
| #endif
 | |
| 
 | |
| int DEFUN(main,(ac,av),
 | |
| int ac AND
 | |
| char *av[])
 | |
| {
 | |
|     unsigned int i;
 | |
|     
 | |
| 
 | |
|     string_type buffer;
 | |
|     string_type pptr;
 | |
|     
 | |
| 
 | |
|     init_string(&buffer);
 | |
|     init_string(&pptr);
 | |
|     init_string(stack+0);
 | |
|     tos=stack+1;
 | |
|     ptr = &pptr;
 | |
|     
 | |
|     add_intrinsic("push_text", push_text);
 | |
|     add_intrinsic("!", bang);
 | |
|     add_intrinsic("@", atsign);
 | |
|     add_intrinsic("hello",hello);    
 | |
|     add_intrinsic("skip_past_newline", skip_past_newline );
 | |
|     add_intrinsic("catstr", icatstr );
 | |
|     add_intrinsic("copy_past_newline", icopy_past_newline );
 | |
|     add_intrinsic("dup", dup );
 | |
|     add_intrinsic("remchar", remchar );
 | |
|     add_intrinsic("get_stuff_in_command", get_stuff_in_command );
 | |
|     add_intrinsic("get_stuff_in_angle", get_stuff_in_angle );
 | |
|     add_intrinsic("do_fancy_stuff", do_fancy_stuff );
 | |
|     add_intrinsic("bulletize", bulletize );
 | |
|     add_intrinsic("courierize", courierize );
 | |
|     add_intrinsic("swap", swap );
 | |
|     add_intrinsic("outputdots", outputdots );
 | |
|     add_intrinsic("exfunstuff", exfunstuff );
 | |
|     add_intrinsic("maybecatstr", maybecatstr );
 | |
|     add_intrinsic("translatecomments", translatecomments );
 | |
|     add_intrinsic("kill_bogus_lines", kill_bogus_lines);
 | |
|     add_intrinsic("indent", indent);
 | |
|     add_intrinsic("quickref", quickref);
 | |
|     add_intrinsic("internalmode", internalmode);
 | |
|     
 | |
|     /* Put a nl at the start */
 | |
|     catchar(&buffer,'\n');
 | |
| 
 | |
|     read_in(&buffer, stdin); 
 | |
|     remove_noncomments(&buffer, ptr);
 | |
|     for (i= 1; i < ac; i++) 
 | |
|     {
 | |
| 	if (av[i][0] == '-')
 | |
| 	{
 | |
| 	    if (av[i][1] == 'f')
 | |
| 	    {
 | |
| 		string_type b;
 | |
| 		FILE *f;
 | |
| 		init_string(&b);
 | |
| 
 | |
| 		f  = fopen(av[i+1],"r");
 | |
| 		if (!f) 
 | |
| 		{
 | |
| 		  fprintf(stderr,"Can't open the input file %s\n",av[i+1]);
 | |
| 		  return 33;
 | |
| 		}
 | |
| 		if(Verbose)  fprintf(stderr, "Reading -f '%s'\n", av[i+1]);
 | |
| 		
 | |
| 		  
 | |
| 		read_in(&b, f);
 | |
| 		if( compile(b.ptr) )  { fclose(f); exit(1); }
 | |
| 		perform();	
 | |
| 		fclose(f);
 | |
| 	    }
 | |
| 	    else    if (av[i][1] == 'i') 
 | |
| 	    {
 | |
| 		internal_wanted = 1;
 | |
| 	    }
 | |
| 	    else    if (av[i][1] == 'v') 
 | |
| 	    {
 | |
| 		Verbose++;
 | |
| 	    }
 | |
| 	}
 | |
| 
 | |
|     }      
 | |
|     write_buffer(stack+0);
 | |
|     return 0;
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 |