home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 5 Edit
/
05-Edit.zip
/
me34src.zip
/
me3
/
mc
/
token.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-01-14
|
12KB
|
488 lines
/*
* token.c : piddle with tokens
*/
/* Copyright 1990, 1991, 1992 Craig Durland
* Distributed under the terms of the GNU General Public License.
* Distributed "as is", without warranties of any kind, but comments,
* suggestions and bug reports are welcome.
*/
#include <stdio.h>
#include <os.h>
#include <const.h>
#include <dtable.h>
#include "mc.h"
#include "mm.h"
#include "opcode.h"
extern char
ebuf[],
*keyword_type_name(), /* in supp.c */
*malloc(), *save_string(), *spoof();
/* ******************************************************************** */
/* *************************** Token Tables *************************** */
/* ******************************************************************** */
/* Notes:
* The tables don't need to be sorted. Most of the lookups are done
* through a hash table, others just walk the array.
*/
oMuttCmd
omuttcmds[] = /* the other Mutt commands, see other_Mutt_cmd() */
{
"ask", ASK, STRING,
"concat", CONCAT, STRING,
"extract-element", EXTRACT_EL, UNKNOWN,
"extract-elements", EXTRACT_ELS,UNKNOWN, /* !!!actually, same as first arg */
"insert-object", INSERT_OBJ, UNKNOWN,
"msg", MSG, STRING,
"remove-elements", REMOVE_ELS, VOID,
};
/* holes: 22, 30, 32-41, 44-59, 74 */
MuttCmd /* all the Mutt keywords, including the omuttcmds[] */
muttcmds[] = /* biggest # = 81 */
{
"!=", 0,
"*", 65,
"*=", 66,
"+", 3,
"+=", 63,
"-", 67,
"-=", 68,
"/", 69,
"/=", 70,
"<", 11,
"<=", 10,
"==", 12,
">", 13,
">=", 14,
"and", 80,
"arg", 43,
"array", 73,
"ask", 32,
"ask-user", 26,
"bool", 62,
"break", 7,
"byte", 75,
"concat", 33,
"cond", 1,
"const", 77,
"continue", 71,
"convert-to", 20,
"defun", 2,
"done", 9,
"extract-element", 24,
"extract-elements", 25,
"floc", 78,
"for", 76,
"goto", 6,
"halt", 16,
"if", 23,
"include", 64,
"insert-object", 18,
"int", 31,
"label", 8,
"length-of", 19,
"list", 27,
"loc", 79,
"msg", 34,
"nargs", 42,
"not", 28,
"novalue", 29,
"or", 81,
"pointer", 72,
"push-arg", 17,
"push-args", 15,
"remove-elements", 21,
"small-int", 61,
"string", 60,
"switch", 4,
"while", 5,
},
modifiers[] = /* the pgm modifiers */
{
"HIDDEN", HIDDEN,
"MAIN", MAIN,
};
static int msize = NITEMS(muttcmds), moders = NITEMS(modifiers);
int omsize = NITEMS(omuttcmds);
/* Yuch !!! */
oMuttCmd *id_to_oMutt(n)
{
switch (n)
{
default: return NULL;
case 32: n = 0; break; /* ask */
case 33: n = 1; break; /* concat */
case 24: n = 2; break; /* extract-element */
case 25: n = 3; break; /* extract-elements */
case 18: n = 4; break; /* insert-object */
case 34: n = 5; break; /* msg */
case 21: n = 6; break; /* remove-elements */
}
return &omuttcmds[n];
}
lookup_pgm_modifier(name) char *name;
{
int i;
for (i = 0; i < moders; i++)
if (0 == strcmp(name, modifiers[i].name)) return modifiers[i].token;
return -1;
}
/* ******************************************************************** */
/* ************************ Keyword Hash Table ************************ */
/* ******************************************************************** */
#include "dhash.h"
/* static void *keyword_hash_table; /* */
static declare_and_init_dTable(keyword_table,KeyWord);
static int num_keywords = 0;
/* Add a keyword to the global hash table.
* Input:
* name : Pointer to name of keyword to add. Must be allocated by
* caller.
* type:
* token: An int to be assocated with name.
* collide: What to do if name is all ready in the table.
* Returns:
* TRUE : Name already in table.
* FALSE : Unique name.
*/
int add_keyword(name, type, token, collide) char *name;
{
ENTRY hkw, *it;
KeyWord *kw;
/* htable(keyword_hash_table); /* */
hkw.key = name;
hkw.data = (void *)num_keywords;
if (!(it = hsearch(hkw,ENTER))) bail("add_keyword: Out of memory!");
if (it->key && it->data != hkw.data) /* already in the table */
{
switch (collide)
{
case 0: /* No collision allowed */
moan("add_keyword1"); /* !!! */
return TRUE;
case 1: /* Complain and ignore */
gripe(spoof(ebuf,"\"%s\": Already in keyword table, ignoring."));
/* FALL THROUGH */
case 2: /* Silent ignore */
return TRUE;
case 3: /* Silent overwrite */
kw = &keyword_table.table[(int)it->data];
kw->type = type;
kw->token = token;
return TRUE;
}
}
if (!xpand_dTable(&keyword_table, 1, 1000,200))
bail("Out of memory! Can't expand keyword table.\n");
kw = &keyword_table.table[num_keywords];
kw->name = name;
kw->type = type;
kw->token = token;
num_keywords++;
return FALSE;
}
void hash_Mutt_keywords()
{
int i;
/* add all the Mutt keywords */
{
MuttCmd *ptr;
for (i = msize, ptr = muttcmds; i--; ptr++)
add_keyword(ptr->name, KWMutt, ptr->token, 0);
}
}
void keyword_init()
{
if (!hcreate(1000)) bail("keyword_init: No memory for hash table!");
/* keyword_hash_table = htable((void *)NULL); /* */
hash_Mutt_keywords();
}
KeyWord *global_look_up(name) char *name;
{
ENTRY hkw, *found;
int i;
/* htable(keyword_hash_table); /* */
hkw.key = name;
if (found = hsearch(hkw,FIND))
{
i = (int)found->data;
return &keyword_table.table[i];
}
return NULL;
}
KeyWord *global_look_for(name, type) char *name;
{
KeyWord *kw;
if ((kw = global_look_up(name)) && kw->type == type) return kw;
return NULL;
}
KeyWord *global_check(name) char *name;
{
KeyWord *kw;
if (kw = global_look_up(name))
{
if (kw->type != KWXToken) /* !!!??? */
{
moan(spoof(ebuf,"\"%s\" already used (as a %s).",
name, keyword_type_name(kw->type)));
return kw;
}
}
return NULL;
}
/* ******************************************************************** */
/* ************************* External Tokens ************************** */
/* ******************************************************************** */
/*
* A token table is stored in a file.
* Format:
* <token number> <token name>
*/
static declare_and_init_dTable(ext_token_table,MuttCmd);
void load_ext_token_table(fname) char *fname;
{
char buf[90], *ptr;
int t;
FILE *fptr;
new_ext(buf,fname,".tok");
if ((fptr = fopen(buf,"r")) == NULL)
{
moan(spoof(ebuf,"Can't open token file \"%s\"!",buf));
return;
}
while ((ptr = fgets(buf,80,fptr)))
{
buf[strlen(buf)-1] = '\0';
t = atoi(ptr);
while (*ptr++ != ' ') ;
ptr = save_string(ptr);
add_keyword(ptr, KWXToken, t, 1);
}
}
/* Look for an external token by value. Returns name.
* Input:
* val: token value to search for if name is NULL.
* Returns:
* NULL : val not found
* pointer to the token name
*/
char *lookup_ext_token_by_value(val)
{
int j;
KeyWord *kw;
kw = keyword_table.table;
for (j = num_keywords; j--; kw++)
if (KWXToken == kw->type && kw->token == val) return kw->name;
return NULL;
}
/* ******************************************************************** */
/* *********************** Conversion Routines ************************ */
/* ******************************************************************** */
int32 atoN(a) char *a; /* convert string to NUMBER */
{
char c, *b=a;
int minus = FALSE, base = 10, z;
int32 n = 0;
if (*a == '-') { a++; minus = TRUE; }
if (*a == '0' && a[1] == 'x') { base = 16; a += 2; }
for (; *a; a++)
{
c = *a; z = 1000;
if ('0' <= c && c <= '9') z = c -'0';
else
if ('a' <= c && c <= 'f') z = c -'a' +10;
else if ('A' <= c && c <= 'F') z = c -'A' +10;
if (z >= base) { moan(spoof(ebuf,"Invalid digit in %s",b)); break; }
n = n*base +z;
}
return minus ? -n : n;
}
/* ******************************************************************** */
/* ************************ Scanning Routines ************************* */
/* ******************************************************************** */
#include <ctype.h>
extern char token[]; /* in mc.c */
extern FILE *lstfile, *srcfile; /* in mc.c */
extern int srcline; /* in mc.c */
extern unsigned int class;
int num_lines_read = 0;
static char pgmtext[514], *xptr;
static int looked = FALSE;
static unsigned int proclass;
int btv = FALSE; /* boolean token value - returned by get_token() */
/* Move the pc to the next nonwhite character.
* Returns: TRUE if ok, FALSE if EoF.
* Notes:
* A trailing newline (if any) is trimmed.
*/
getsrc()
{
char *ptr;
if ((xptr = fgets(pgmtext,512,srcfile)) == NULL) return FALSE;
if (*(ptr = xptr + strlen(xptr) -1) == '\n') *ptr = '\0';
num_lines_read++;
srcline++;
if (lstfile) fprintf(lstfile,"LINE %d: %s\n",srcline,xptr);
return TRUE;
}
/* skip comment => skip to next line */
/* EoF: Ok if comment is last thing in buffer/file */
#define nocomment() getsrc()
static scan()
{
top: /* incase got to get a new line */
while (isspace(*xptr)) xptr++; /* delete leading white space */
if (*xptr == '\0')
if (getsrc()) goto top; else return FALSE;
if (*xptr == ';') if (nocomment()) goto top; else return FALSE;
return TRUE;
}
/* returns: TRUE (all ok), FALSE (something screwed up)
*/
void get_token()
{
register char *ptr;
if (looked) { looked = FALSE; class = proclass; return; }
*(ptr = token) = '\0'; class = TOKEN;
if (!scan()) { class = proclass = SEOF; return; }
switch (*xptr)
{
case '\'': /* string literal: 'string', ''=>' */
for (xptr++; *xptr && ptr < (token +250); xptr++)
if (*xptr == '\'' && *++xptr != '\'') goto uggg;
else *ptr++ = *xptr;
if (*xptr == '\0') bitch("String not terminated!");
uggg:
class = STRING;
break;
case '\"': /* "string": knows about \ (quote), ^ (control) */
for (xptr++; *xptr && *xptr != '\"' && ptr < (token +250); xptr++)
switch (*xptr)
{
case '\\': *ptr++ = *++xptr; break; /* \ : quote next char */
case '^': *ptr++ = *++xptr ^ 0x40; break; /* ^ => cntl char */
default: *ptr++ = *xptr;
}
if (*xptr == '\0') bitch("String not terminated!");
xptr++; class = STRING;
break;
default: /* get a token or number */
while (*xptr && !isspace(*xptr))
{
if (strchr("(){};",*xptr))
{
if (ptr == token)
{
class = DELIMITER;
if ( xptr[0] == '{' && xptr[1] == '{')
{ *ptr++ = START_IPGM; xptr += 2; }
else
if (xptr[0] == '}' && xptr[1] == '}')
{ *ptr++ = END_IPGM; xptr += 2; }
else *ptr++ = *xptr++;
}
break;
}
*ptr++ = *xptr++;
}
}
*ptr = '\0';
if (class == TOKEN)
{
if ((isdigit(*token) || (*token == '-' && isdigit(*(token+1)))))
class = NUMBER;
else if (strcmp(token,"FALSE") == 0) { class = BOOLEAN; btv = FALSE; }
else if (strcmp(token,"TRUE") == 0) { class = BOOLEAN; btv = TRUE; }
}
proclass = class;
return;
}
/* Note: gotta be careful class don't get trashed between
* lookahead() & get_token()
*/
void lookahead()
{
if (looked) { class = proclass; return; }
get_token(); looked = TRUE;
}
typedef struct Inca { struct Inca *next; char fname[1]; } Inca;
static Inca *inchead = NULL;
include(fname) char *fname;
{
register Inca *ptr;
for (ptr = inchead; ptr; ptr = ptr->next)
if (strcmp(ptr->fname,fname) == 0)
{
gripe(spoof(ebuf,"Already included: %s. Ignoring.",fname));
nocomment(); /* bloto rest of line */
return UNKNOWN;
}
if (NULL == (ptr = (Inca *)malloc(sizeof(Inca) +strlen(fname))))
bail("Out of memory in include()");
strcpy(ptr->fname,fname);
ptr->next = inchead; inchead = ptr;
pilefile(fname,TRUE);
getsrc(); /* prime scan() */
return UNKNOWN;
}