⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gwart.c

📁 使用Kermit协议传输文件的程序
💻 C
字号:
/*  G W A R T  --  GNU version of Wart  A small subset of "lex" sufficient for converting the Kermit  protocol state table from lex notation to C.  Authors:    Jeff Damens, Frank da Cruz    The Kermit Project, Columbia University    http://www.columbia.edu/kermit/    kermit@columbia.edu  Copyright (C) 1984, 1999,  The Trustees of Columbia University in the City of New York.  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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA*//* * input format is: *  lines to be copied | %state <state names...> *  %% * <state> | <state,state,...> CHAR  { actions } * ... *  %% *  more lines to be copied */#include <stdio.h>#include <ctype.h>#include "gkermit.h"#define TBL_TYPE "short"		/* C data type of state table */#define C_L 014				/* Formfeed */#define SEP 1				/* Token types */#define LBRACK 2#define RBRACK 3#define WORD 4#define COMMA 5/* Storage sizes */#define MAXSTATES 50			/* max number of states */#define MAXWORD 50			/* max # of chars/word */#define SBYTES ((MAXSTATES+6)/8)	/* # of bytes for state bitmask *//* Name of gwart function in generated program */#ifndef FNAME#define FNAME "gwart"#endif /* FNAME *//* Structure for state information */struct transx {    CHAR states[SBYTES];		/* included states */    int anyst;				/* true if this good from any state */    CHAR inchr;				/* input character */    int actno;				/* associated action */    struct transx *nxt;};					/* next transition */typedef struct transx *trans;/* Function prototypes */_MYPROTOTYPE( VOID fatal, (char *) );_MYPROTOTYPE( VOID setwstate, (int, trans) );_MYPROTOTYPE( int teststate, (int, trans) );_MYPROTOTYPE( trans rdinput, (FILE *, FILE *) );_MYPROTOTYPE( VOID initial, (FILE *, FILE *) );_MYPROTOTYPE( int isin, (char *, int) );_MYPROTOTYPE( int isword, (int) );_MYPROTOTYPE( VOID rdword, (FILE *, char *) );_MYPROTOTYPE( VOID rdstates, (FILE *, FILE *) );_MYPROTOTYPE( trans newtrans, (void) );_MYPROTOTYPE( trans rdrules, (FILE *, FILE *) );_MYPROTOTYPE( VOID statelist, (FILE *, trans) );_MYPROTOTYPE( VOID copyact, (FILE *, FILE *, int) );_MYPROTOTYPE( int faction, (trans, int, int) );_MYPROTOTYPE( VOID emptytbl, (void) );_MYPROTOTYPE( VOID addaction, (int, int, int) );_MYPROTOTYPE( VOID writetbl, (FILE *) );_MYPROTOTYPE( VOID warray, (FILE *, char *, int [], int, char *) );_MYPROTOTYPE( VOID prolog, (FILE *) );_MYPROTOTYPE( VOID epilogue, (FILE *) );_MYPROTOTYPE( VOID copyrest, (FILE *, FILE *) );_MYPROTOTYPE( int gettoken, (FILE *) );_MYPROTOTYPE( VOID rdcmnt, (FILE *) );_MYPROTOTYPE( VOID clrhash, (void) );_MYPROTOTYPE( int hash, (char *) );_MYPROTOTYPE( VOID enter, (char *, int) );_MYPROTOTYPE( int lkup, (char *) );_MYPROTOTYPE( static char* copy, (char *s) );/* Variables and tables */int lines, nstates, nacts;int tbl[MAXSTATES*96];char tokval[MAXWORD];char *tbl_type = TBL_TYPE;char *txt1 = "\n#define BEGIN state =\n\nint state = 0;\n\nint\n";char *fname = FNAME;			/* Generated function name goes here *//* Rest of program... */char *txt2 = "()\n\{\n\    int c,actno;\n\    extern ";/* Data type of state table is inserted here (short or int) */char *txt2a =" tbl[];\n\    while (1) {\n\	c = input() - 32;\n\	if (c < 0 || c > 95) c = 0;\n";char *txt2b = "	if ((actno = tbl[c + state*96]) != -1)\n\	    switch(actno) {\n";/* this program's output goes here, followed by final text... */char *txt3 = "\n	    }\n    }\n}\n\n";/* * turn on the bit associated with the given state * */VOIDsetwstate(state,t) int state; trans t; {    int idx,msk;    idx = state/8;			/* byte associated with state */    msk = 0x80 >> (state % 8);		/* bit mask for state */    t->states[idx] |= msk;}/* * see if the state is involved in the transition * */intteststate(state,t) int state; trans t; {    int idx,msk;    idx = state/8;    msk = 0x80 >> (state % 8);    return(t->states[idx] & msk);}/* * read input from here... * */transrdinput(infp,outfp) FILE *infp, *outfp; {    trans x;    lines = 1;				/* line counter */    nstates = 0;			/* no states */    nacts = 0;				/* no actions yet */    fprintf(outfp,"\n%c* WARNING -- This C source program generated by ",'/');    fprintf(outfp,"gwart preprocessor. */\n");    fprintf(outfp,"%c* Do not edit this file; edit the gwart-format ",'/');    fprintf(outfp,"source file instead, */\n");    fprintf(outfp,"%c* and then run it through gwart to produce a new ",'/');    fprintf(outfp,"C source file.     */\n\n");    initial(infp,outfp);		/* read state names, initial defs */    prolog(outfp);			/* write out our initial code */    x = rdrules(infp,outfp);		/* read rules */    epilogue(outfp);			/* write out epilogue code */    return(x);}/* * initial - read initial definitions and state names.  Returns * on EOF or %%. * */VOIDinitial(infp,outfp) FILE *infp, *outfp; {    int c;    char wordbuf[MAXWORD];    while ((c = getc(infp)) != EOF) {	if (c == '%') {	    rdword(infp,wordbuf);	    if (strcmp(wordbuf,"states") == 0)	      rdstates(infp,outfp);	    else if (strcmp(wordbuf,"%") == 0) return;	    else fprintf(outfp,"%%%s",wordbuf);	}	else putc(c,outfp);	if (c == '\n') lines++;    }}/* * boolean function to tell if the given character can be part of * a word. * */intisin(s,c) char *s; int c; {    for (; *s != '\0'; s++)      if (*s == (char) c) return(1);    return(0);}intisword(c) int c; {    static char special[] = ".%_-$@";	/* these are allowable */    return(isalnum(c) || isin(special,c));}/* * read the next word into the given buffer. * */VOIDrdword(fp,buf) FILE *fp; char *buf; {    int len = 0,c;    while (isword(c = getc(fp)) && ++len < MAXWORD) *buf++ = (char) c;    *buf++ = '\0';			/* tie off word */    ungetc(c,fp);			/* put break char back */}/* * read state names, up to a newline. * */VOIDrdstates(fp,ofp) FILE *fp,*ofp; {    int c;    char wordbuf[MAXWORD];    while ((c = getc(fp)) != EOF && c != '\n') {	if (isspace(c) || c == C_L) continue;	/* skip whitespace */	ungetc(c,fp);			/* put char back */	rdword(fp,wordbuf);		/* read the whole word */	enter(wordbuf,++nstates);	/* put into symbol tbl */	fprintf(ofp,"#define %s %d\n",wordbuf,nstates);    }    lines++;}/* * allocate a new, empty transition node * */transnewtrans() {    trans new;    int i;    new = (trans) malloc(sizeof (struct transx));    for (i=0; i<SBYTES; i++) new->states[i] = 0;    new->anyst = 0;    new->nxt = NULL;    return(new);}/* * read all the rules. * */transrdrules(fp,out) FILE *fp,*out; {    trans head,cur,prev;    int curtok;    head = cur = prev = NULL;    while ((curtok = gettoken(fp)) != SEP)      switch(curtok) {	case LBRACK:	  if (cur == NULL)	    cur = newtrans();	  else	    fatal("duplicate state list");	  statelist(fp,cur);		/* set states */	  continue;			/* prepare to read char */	case WORD:	  if ((int)strlen(tokval) != 1)	    fatal("multiple chars in state");	  if (cur == NULL) {	      cur = newtrans();	      cur->anyst = 1;	  }	  cur->actno = ++nacts;	  cur->inchr = (char) (tokval[0] - 32);	  if (head == NULL)	    head = cur;	  else	    prev->nxt = cur;	  prev = cur;	  cur = NULL;	  copyact(fp,out,nacts);	  break;	default: fatal("bad input format");      }    return(head);}/* * read a list of (comma-separated) states, set them in the * given transition. * */VOIDstatelist(fp,t) FILE *fp; trans t; {    int curtok,sval;    curtok = COMMA;    while (curtok != RBRACK) {	if (curtok != COMMA) fatal("missing comma");	if ((curtok = gettoken(fp)) != WORD) fatal("missing state name");	if ((sval = lkup(tokval)) == -1) {	    fprintf(stderr,"state %s undefined\n",tokval);	    fatal("undefined state");	}	setwstate(sval,t);	curtok = gettoken(fp);    }}/* * copy an action from the input to the output file * */VOIDcopyact(inp,outp,actno) FILE *inp,*outp; int actno; {    int c,bcnt;    fprintf(outp,"case %d:\n",actno);    while (c = getc(inp), (isspace(c) || c == C_L))      if (c == '\n') lines++;    if (c == '{') {	bcnt = 1;	fputs("    {",outp);	while (bcnt > 0 && (c = getc(inp)) != EOF) {	    if (c == '{') bcnt++;	    else if (c == '}') bcnt--;	    else if (c == '\n') lines++;	    putc(c,outp);	}	if (bcnt > 0) fatal("action doesn't end");    } else {	while (c != '\n' && c != EOF) {	    putc(c,outp);	    c = getc(inp);	}	lines++;    }    fprintf(outp,"\n    break;\n");}/* * find the action associated with a given character and state. * returns -1 if one can't be found. * */intfaction(hd,state,chr) trans hd; int state,chr; {    while (hd != NULL) {	if (hd->anyst || teststate(state,hd))	  if (hd->inchr == ('.' - 32) || hd->inchr == (char) chr)	    return(hd->actno);	hd = hd->nxt;    }    return(-1);}/* * empty the table... * */VOIDemptytbl() {    int i;    for (i=0; i<nstates*96; i++) tbl[i] = -1;}/* * add the specified action to the output for the given state and chr. * */VOIDaddaction(act,state,chr) int act,state,chr; {    tbl[state*96 + chr] = act;}VOIDwritetbl(fp) FILE *fp; {    warray(fp,"tbl",tbl,96*(nstates+1),TBL_TYPE);}/* * write an array to the output file, given its name and size. * */VOIDwarray(fp,nam,cont,siz,typ) FILE *fp; char *nam; int cont[],siz; char *typ; {    int i;    fprintf(fp,"%s %s[] = {\n",typ,nam);    for (i = 0; i < siz - 1; ) {	fprintf(fp," %2d,",cont[i]);	if ((++i % 16) == 0) putc('\n',fp);    }    fprintf(fp,"%2d\n};\n",cont[siz-1]);}intmain(argc,argv) int argc; char **argv; {    trans head;    int state,c;    FILE *infile,*outfile;    if (argc > 1) {	if ((infile = fopen(argv[1],"r")) == NULL) {	    fprintf(stderr,"Can't open %s\n",argv[1]);	    fatal("unreadable input file");	}    } else infile = stdin;    if (argc > 2) {	if ((outfile = fopen(argv[2],"w")) == NULL) {	    fprintf(stderr,"Can't write to %s\n",argv[2]);	    fatal("bad output file");	}    } else outfile = stdout;    clrhash();				/* empty hash table */    head = rdinput(infile,outfile);	/* read input file */    emptytbl();				/* empty our tables */    for (state = 0; state <= nstates; state++)      for (c = 1; c < 96; c++)		/* find actions, */	addaction(faction(head,state,c),state,c); /* add to tbl */    writetbl(outfile);    copyrest(infile,outfile);    printf("%d states, %d actions\n",nstates,nacts);    exit(0);}/* * fatal error handler * */VOIDfatal(msg) char *msg; {    fprintf(stderr,"error in line %d: %s\n",lines,msg);    exit(1);}VOIDprolog(outfp) FILE *outfp; {    int c;    while ((c = *txt1++)     != '\0') putc(c,outfp);    while ((c = *fname++)    != '\0') putc(c,outfp);    while ((c = *txt2++)     != '\0') putc(c,outfp);    while ((c = *tbl_type++) != '\0') putc(c,outfp);    while ((c = *txt2a++)    != '\0') putc(c,outfp);    while ((c = *txt2b++)    != '\0') putc(c,outfp);}VOIDepilogue(outfp) FILE *outfp; {    int c;    while ((c = *txt3++) != '\0') putc(c,outfp);}VOIDcopyrest(in,out) FILE *in,*out; {    int c;    while ((c = getc(in)) != EOF) putc(c,out);}/* * gettoken - returns token type of next token, sets tokval * to the string value of the token if appropriate. * */intgettoken(fp) FILE *fp; {    int c;    while (1) {				/* loop if reading comments... */	do {	    c = getc(fp);	    if (c == '\n') lines++;	} while ((isspace(c) || c == C_L)); /* skip whitespace */	switch(c) {	  case EOF:	    return(SEP);	  case '%':	    if ((c = getc(fp)) == '%') return(SEP);	    tokval[0] = '%';	    tokval[1] = (char) c;	    rdword(fp,tokval+2);	    return(WORD);	  case '<':	    return(LBRACK);	  case '>':	    return(RBRACK);	  case ',':	    return(COMMA);	  case '/':	    if ((c = getc(fp)) == '*') {		rdcmnt(fp);		/* skip over the comment */		continue;	    } else {			/* and keep looping */		ungetc(c,fp);		/* put this back into input */		c = '/';		/* put character back, fall thru */	    }	  default:	    if (isword(c)) {		ungetc(c,fp);		rdword(fp,tokval);		return(WORD);	    } else fatal("Invalid character in input");	}    }}/* * skip over a comment * */VOIDrdcmnt(fp) FILE *fp; {    int c,star,prcnt;    prcnt = star = 0;			/* no star seen yet */    while (!((c = getc(fp)) == '/' && star)) {	if (c == EOF || (prcnt && c == '%')) fatal("Unterminated comment");	prcnt = (c == '%');	star = (c == '*');	if (c == '\n') lines++;    }}/* * symbol table management for gwart * * entry points: *   clrhash - empty hash table. *   enter - enter a name into the symbol table *   lkup - find a name's value in the symbol table. */#define HASHSIZE 101			/* # of entries in hash table */struct sym {    char *name;				/* symbol name */    int val;				/* value */    struct sym *hnxt;			/* next on collision chain */} *htab[HASHSIZE];			/* the hash table *//* * empty the hash table before using it... * */VOIDclrhash() {    int i;    for (i=0; i<HASHSIZE; i++) htab[i] = NULL;}/* * compute the value of the hash for a symbol * */inthash(name) char *name; {    int sum;    for (sum = 0; *name != '\0'; name++) sum += (sum + *name);    sum %= HASHSIZE;			/* take sum mod hashsize */    if (sum < 0) sum += HASHSIZE;	/* disallow negative hash value */    return(sum);}/* * make a private copy of a string... * */static char*copy(s) char *s; {    char *new;    new = (char *) malloc((int)strlen(s) + 1);    strcpy(new,s);    return(new);}/* * enter state name into the hash table * */VOIDenter(name,svalue) char *name; int svalue; {    int h;    struct sym *cur;    if (lkup(name) != -1) {	fprintf(stderr,"state \"%s\" appears twice...\n", name);	exit(1);    }    h = hash(name);    cur = (struct sym *)malloc(sizeof (struct sym));    cur->name = copy(name);    cur->val = svalue;    cur->hnxt = htab[h];    htab[h] = cur;}/* * find name in the symbol table, return its value.  Returns -1 * if not found. * */intlkup(name) char *name; {    struct sym *cur;    for (cur = htab[hash(name)]; cur != NULL; cur = cur->hnxt)      if (strcmp(cur->name,name) == 0) return(cur->val);    return(-1);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -