Trailing-Edge
-
PDP-10 Archives
-
SRI_NIC_PERM_FS_1_19910112
-
c/user/ncref/parses.c
There are no other files named parses.c in the archive.
/* Fixed screwy function definition criteria --KLH 3/16/88 */
#include <stdio.h>
#include <ctype.h>
#include "crdef.h"
char *getkey();
/*
* parse - Initial source code parsing
*
* Remove extraneous field delimiters & comment fields and detect
* presense of parentheses as cue to do further processing.
*/
parse ( )
{
int c, lastc, nlastc;
int i,comment,paren1,no_eof,quot1,quot2,incdef;
i = comment = paren1 = quot1 = quot2 = incdef = 0;
nlastc = lastc = '\0';
ln = pg = no_eof = 1;
/* parse while no end-of-file and no errors */
while (no_eof)
{
/* check for string array length exceeded - print error
and exit if so */
if (i >= STRSZ) {
if (paren1) {
printf("string size exceeded %d-%d\n%s\n",
pg,ln,string);
exit( );
}
else {
i= incdef = 0;
i = backup();
}
}
/* get char from source - if char is an end-of-file or error
condition, reset no_eof flag to stop processing after
this char and treat it as a delimiting semicolon */
if ( (c=getc(iop)) < 0) {
no_eof=0; c= ';' ; }
/* process in this block if inside comment field */
if (comment)
{
switch (c) {
case '*' :
/* record asterisk, possible comment delimit */
lastc = c;
break;
case '/' :
/* if astr. precedes, end comment field */
if (lastc == '*') {
comment = 0;
lastc = nlastc;}
break;
case '\n' :
/* incr location, save if not at string
beginning */
incloc( );
if (i != 0) {
if(nlastc ==' ') nlastc=string[i-1] ='\n';
else nlastc = string[i++] = '\n'; }
default :
/* ignore all other chars inside comment
field */
lastc = c;
break;
}
}
/* process chars outside comment field here */
else
{
switch(c) {
case '#' :
/* looking for include or define statement */
if(!quot1 && !quot2) {
if(i == 0 || string[i-1] == '\n')
incdef++;
else goto other;
break;
}
break;
case '*' :
/* on comment delimiter, set flag and back
up to remove '/' from string */
if (!quot1 && !quot2)
{ if (lastc == '/') {
comment = 1; i--; }
else string[i++] = c;
}
lastc = c;
break;
case '/' :
/* save as possible comment delimiter */
if (!quot1 && !quot2)
{ nlastc = lastc;
string[i++] = c;
}
lastc = c;
break;
case '"' :
/* set flag to ignore chars in double quotes */
if (!quot1)
if (lastc != '\\')
quot2 ^= 01;
lastc = c;
break;
case '\'' :
/* set flag to ignore chars in single quotes */
if (!quot2)
if (lastc != '\\')
quot1 ^= 01;
lastc = c;
break;
case '\\' :
/* cancel effect of backslash if another
follows */
if ( lastc == '\\')
lastc = 0;
else lastc = c;
break;
case '\n' :
/* insert newline if occurs within char str*/
if (incdef) {
lastc = string[i] = '\0';
if (paren1)
parse2();
i = paren1 = incdef = 0;
break;
}
incloc( );
if (i != 0) {
if(lastc ==' ') string[i-1] ='\n';
else string[i++] = '\n'; }
lastc = c;
break;
case '\t' :
/* process tab as blank */
case ' ' :
/* do not save blanks if occur at string's
beginning, or if newline or other blank
already delimits */
if (!quot1 && !quot2) {
if((i !=0) && (lastc !=' ') && (lastc !='\n'))
lastc = string[i++] = ' ' ;
break;
}
else {
lastc = c;
break;
}
case ';' :
/* semicolon delimits string */
if ( !quot1 && !quot2)
{ lastc = string[i] = '\0';
/* if string contains a parentheses,
do further parsing to look for
function reference */
if (paren1)
parse2();
/* reset flags to get next string */
i = paren1 = 0;
break;
}
else {
lastc = c;
break;
}
case '(' :
/* indicate parentheses occurred, then
process as any other char */
if (quot1 || quot2)
{ lastc = c;
break;
}
paren1 ++;
default:
/* other chars - record and set line and
page pntrs when at start of statement
string */
other:
if (!quot1 && !quot2)
{ if (i == 0) { rpg=pg; rln =ln; }
string[i++] = c;
}
lastc = c;
break;
}
}
}
return;
}
/*
* parse2 - Complete processing of statements which contain potential
* function references.
*
* Obtain potential function names, determine valid references, detect
* defintions, and record all valid occurences in the function tree
* structure.
*/
parse2( )
{
int j;
int ch;
j = 0;
/* process statement string until null encountered */
while ( (ch=string[j++]) != '\0')
{
switch (ch)
{
case '\n' :
newcase ( );
break;
case '(' :
parcase (j);
break;
default:
break;
}
}
return;
}
/*
* newcase - On newline char, increment reference line and page counts
*/
newcase( )
{
rln++; /* incr line cnt */
if (rln > rpg*PAGESZ) rpg++; /* if new page indicated, */
/* incr page count */
}
/*
* parcase - On open parentheses, see if a function name precedes and,
* if so, record the reference.
*/
parcase (j)
int j;
{
int js, nlcnt;
char *kpntr;
js = j-2; /* j points to next char; back up */
/* to char which precedes paren*/
if (string[js] == ' ') js--; /* if preceding char is blank, */
/* back up again to nonblank */
nlcnt = 0; /* zero the newline cnt */
while(string[js] == '\n') /* back up past newline chars if */
{js--; nlcnt++;} /* any and count them */
/* collect string of chars preceding the parentheses as a "keystring"
and return a pointer to the keystring's beginning. */
kpntr = getkey(js);
if (kpntr)
{
/* if pointer is not zero, a valid keystring was found. Use
'lookup' to determine if keystring is a statement keyword.
If not, return is less than zero, and keystring may be a
valid function name. Call 'found' to do final determination
recording reference if it is indicated. */
if ( (lookup(kpntr,statkey)) < 0)
{
found (kpntr,nlcnt,j);
}
}
return;
}
/*
* getkey - get the keystring preceding the parentheses; dismiss all but
* those chars which are legal in a function name.
*/
char *
getkey (js)
int js; /* js init pnts to the end of potential */
/* keystring */
{
int k,C;
k = KEYSZ; /* k indexes the save area for the keystring*/
/* get the preceding name */
while (js >= 0)
{
C = string[js--];
/* make sure char is legal in a function name - if not, stop
collecting keystring */
if ( ('a' <= C && C <= 'z') || ('A' <= C && C <= 'Z') ||
(C =='_') || ('0' <= C && C <= '9') )
{ if (k < 1) { k=KEYSZ; js= -1; }
else key[--k] = C;
}
else js = -1;
}
/* if a valid keystring found, (index k has changed), return its address
otherwise, return zero. */
if (k < KEYSZ) return (&key[k]);
else return (0);
}
/*
* found - when valid function found, determine its location and type and
* save info in the data structure using 'insfun'.
*/
found (kpntr,nlcnt,j)
int nlcnt,j;
char *kpntr;
{ struct fnode *insfun();
scopy(kpntr,arg->fname); /* insert func name in arg list */
arg->fline = rln-nlcnt; /* calc line and page no.s */
if ( (rln-nlcnt) <= (rpg-1)*PAGESZ)
arg->fpage = (rpg-1);
else arg->fpage = rpg;
/* Determine type of function reference or return now if no valid
reference indicated */
if( (arg->ftype = whatype(j)) < 0)
return;
/* finally, record the data if valid reference */
top = insfun (top,arg);
return;
}
/*
* whatype - determine if function is being defined or called
*
* If function name is followed by an open bracket or by a
* declaration keyword, then it is a definition - return zero.
* Otherwise, return a one - it is a function call.
*/
whatype (jp)
int jp; /* jp pnts to char following the open paren in */
/* the func refer. */
{
int c1;
int k,rt;
/* search for close paren (end of func arg list) or return with
negative on end of file */
while( ((c1=string[jp++]) != ')') && (c1 != '\0') );
if (!c1) return(-1);
/* skip succeeding blanks or newlines */
if (string[jp] == ' ') jp++;
while (string[jp] == '\n') jp++;
/* if open bracket is next non-delimiting char, then this must
be a func definition - return type zero; otherwise, see if
a declaration keyword follows immediately. */
if (string[jp] == '{') return(0);
else {
/* get succeeding chars, see if they form a potential
declaration keyword. Reset flag "rt" if not */
k = 0;
rt = 1;
while (k <= KEYSZ)
{
/* collect legal keyword chars until delimiter
found. reset flag on illegal char or excessive
length. */
c1 = string[jp++];
switch (c1) {
case '\n' :
case ' ' :
case '\0' :
/* on delimiter, set null and exit collection */
key[k] = '\0';
k = (KEYSZ+1);
break;
default :
#if 1 /* New code --KLH 3/16/88 */
if((isalnum(c1) || c1 == '_') && k<KEYSZ )
#else
/* if char not small case alphabetic it is
illegal - string must not exceed size
KEYSZ */
if( ('a' <= c1 && c1 <= 'z') && k<KEYSZ )
#endif
key[k++] = c1;
else { rt = 0; k = (KEYSZ+1); }
}
}
/* return one on no possible keyword string (rt zero) .*/
if (rt == 0) return(1);
else {
/* look up string in declaration key list - if
returned value is neg. then it is not a decl key
so this must be a func call. On plus, decl key
found means it is a func definition. Return
appropriate values. */
#if 1 /* New code --KLH 3/16/88 */
/* Always return 0 (funct def) if next token is any kind of legal
** identifier.
*/
return !(isalpha(key[0]) || key[0] == '_');
#else
rt = lookup(key,declkey);
if (rt < 0) return(1);
else return(0);
#endif
}
}
}
backup() {
register i,k;
rln = ln; rpg = pg;
k = STRSZ -17;
for( i = 0; k < STRSZ; ) string[i++] = string[k++];
for ( k = 0; k <= i; ) if (string[k++] == '\n') rln--;
if (rln < (rpg-1) * PAGESZ) rpg--;
return(i);
}