📄 macro.c
字号:
/* once a 'collector' or 'optional' is found, */ /* following ones must be of the same type */ if (!coll && formal_type==Kcollector || !opt && formal_type==Koptional) { fprintf( stderr, "%s Evaluation of keywordDefine of (%s:\n", lineno(), keywords[curr_macro]); fprintf( stderr, " (formal %s must also have (%s attached!\n", f->data.tree->data.token, keywords[formal_type]); err_count++; } } DEBUG(6) "macro: definition has %d args (%d collector, %d optional)\n", cnt, ncolls, nopts); if (ncolls>0 && nopts>0) return(NULL); /*Illegal, message already made*/ if (ncolls>0) keywordlevelused=3; result = NULL; /* repeat to fill collector type arguments */ for (cnt=0; call && (cnt==0||ncolls>0); cnt++) /* scan over the formals, one assignment for each */ for (f=formal, rp= &result; f; f=f->next, rp= &((*rp)->next)) { formal_asgn = f->data.tree->data.token; coll = (ncolls)?locate( f, Kcollector, 0):0; opt = (nopts)?locate( f, Koptional, 0):0; if (!call && !opt) break; /* error: no actual args for non-opt*/ if (cnt>0 && !coll) continue; /*skip non-coll after 1st round*/ if (cnt==0) /*create list to contain result*/ { *rp = get_parsetree(); (*rp)->type = Kformal; /*misuse type field as forEach flag*/ (*rp)->data.tree = get_parsetree(); (*rp)->data.tree->type = IDENT; /* attach par name */ (*rp)->data.tree->data.token = formal_asgn; } DEBUG(7) "macro: attaching value %d to formal argument '%s'\n", cnt+1, formal_asgn); for (vp= &((*rp)->data.tree->next); *vp; vp= &((*vp)->next)); /* locate end of values list */ if (call) /* value available*/ *vp = cpy_parsetree( call); else /* use (optional field */ { DEBUG(7) "macro: no actual, evaluate '(optional'\n"); *vp = buildmacro( result, opt->data.tree); if (!(*vp) || (*vp)->next) { fprintf( stderr, "%s Evaluation of keywordDefine of (%s:\n", lineno(), keywords[curr_macro]); fprintf( stderr, " (formal %s (optional returns %s!\n", formal_asgn, (*vp)?"several values":"empty value"); err_count++; } } if (call) call = call->next; } formal_asgn = NULL; if (call || f) { fprintf( stderr, "%s macro call (%s has too %s arguments!\n", lineno(), keywords[curr_macro], call ? "many" : "few"); err_count++; } if (debug>=4) for (rp= &result; *rp; rp= &((*rp)->next)) { fprintf( stderr, "call (%s, arg '%s' =", keywords[curr_macro], (*rp)->data.tree->data.token); for (vp= &((*rp)->data.tree->next); *vp; vp= &((*vp)->next)) fprintf( stderr, " %s", treetxt(*vp)); fprintf( stderr, "\n"); } return( result);}/* create parsetree from a macro-body definition and an assigned parameter set*/static PARSETREE *buildmacro( args, body)PARSETREE *args, *body;{ PARSETREE *result, **pr, *pf, *pa, **pp; char *parname; int i, n; DEBUG(5) "Entering buildmacro: curr_macro=%s, formal_asgn=%s\n", keywords[curr_macro], formal_asgn?formal_asgn:"-"); for (result=NULL, pr= &result; body; body=body->next) switch( body->type) { case Kbuild: DEBUG(6) " processing (build %s\n", body->data.tree->data.token); *pr = get_parsetree(); (*pr)->type = key_hash( body->data.tree->data.token, 0); if ((*pr)->type == KEYWORD) /* yet unknown keyword: edif input error */ { fprintf( stderr, "%s and %d: (build of unknown keyword '%s', form skipped!\n", lineno(), body->line, body->data.tree->data.token); err_count++; put_parsetree( *pr); *pr = NULL; } else /* O.K. */ { (*pr)->data.tree = buildmacro( args, body->data.tree->next); pr = &((*pr)->next); } break; case Kactual: DEBUG(6) " processing (actual %s\n", body->data.tree->data.token); parname = body->data.tree->data.token; pf = find_actual( args, parname); if (!pf) break; /* error message already generated */ if (pf->type==KforEach) /* take one element of forEach*/ { *pr = cpy_parsetree( pf->data.tree->next); pr = &((*pr)->next); } else /* take actual list*/ { for (pf=pf->data.tree->next; pf; pf=pf->next) { *pr = cpy_parsetree( pf); pr = &((*pr)->next); } } break; case Kliteral: DEBUG(6) " processing (literal ...\n"); for (pf=body->data.tree; pf; pf = pf->next) { *pr = cpy_parsetree( pf); pr = &((*pr)->next); } break; case KforEach: keywordlevelused = 3; /*** initialise loop ****/ DEBUG(6) " starting (forEach\n"); pa = NULL; pf = body->data.tree; if (pf->type == KformalList) pf = pf->data.tree; while (pf && pf->type==IDENT) { pa = find_actual( args, pf->data.token); if (!pa) break; /* set forEach loop flag */ pa->type = KforEach; /* create cycle of actual values, count items*/ n=0; for (pp= &(pa->data.tree->next); *pp; pp= &((*pp)->next)) n++; *pp = pa->data.tree->next; pf = pf->next; } if (!pa) break; /***** iterate body ******/ for (i=0; i<n; i++) { *pr = buildmacro( args, body->data.tree->next); while (*pr) pr = &((*pr)->next); /* next actual values by rotating list */ pf = body->data.tree; if (pf->type == KformalList) pf = pf->data.tree; while (pf && pf->type==IDENT) { pa = find_actual( args, pf->data.token); pa = pa->data.tree; pa->next = pa->next->next; pf = pf->next; } DEBUG(6) " foreach: cycle %d finished\n", i); } /***** terminate loop ******/ pf = body->data.tree; if (pf->type == KformalList) pf = pf->data.tree; while (pf && pf->type==IDENT) { pa = find_actual( args, pf->data.token); pa->type = Kformal; /* break cycle again in normal list*/ for (pp= &(pa->data.tree->next), i=0; i<n; pp= &((*pp)->next), i++); *pp = NULL; pf = pf->next; } break; case Kcomment: break; } DEBUG(5) "buildmacro exit: makes )\n"); return( result);}static PARSETREE *find_actual( args, name)PARSETREE *args;char *name;{ PARSETREE *pf; for (pf=args; pf && pf->data.tree->data.token != name; pf = pf->next); /* find actual argument */ if (!pf) { fprintf( stderr, "%s Evaluating keywordDefinition '(%s':\n", lineno(), keywords[curr_macro]); if (formal_asgn) fprintf( stderr, " (formal %s illegally references %s!\n", formal_asgn, name); else fprintf( stderr, " formal parameter %s unknown!\n", name); err_count++; } return(pf);}static PARSETREE *cpy_parsetree( org)PARSETREE *org;{ PARSETREE *cpy, **p; if (!org) return(NULL); cpy = get_parsetree(); cpy->type = org->type; switch( cpy->type) { case IDENT: case STRING: cpy->data.token = org->data.token; break; case NUMBER: cpy->data.ival = org->data.ival; break; } if (!ISKEYWORD(org->type)) return(cpy); for (org=org->data.tree, p= &(cpy->data.tree); org; org = org->next, p= &((*p)->next)) *p = cpy_parsetree( org); return( cpy);}/**** aid for generating err messages ***/char *lineno(){ static char buf[20]; if (mlines[1]>mlines[0]) sprintf( buf, "Line %d-%d:", mlines[0], mlines[1]); else sprintf( buf, "Line %d:", yy_create_edf_lineno); return(buf);}char *tokentxt(){ char c1, c2, *pc; switch(token->type) { case STRING: if (mlines[0]) strcpy( yy_create_edf_text, token->data.token); if (strlen(yy_create_edf_text)>25) strcpy( yy_create_edf_text+22, "..."); return( yy_create_edf_text); case IDENT: if (mlines[0]) return( token->data.token); else return( yy_create_edf_text); case NUMBER: if (mlines[0]) sprintf( yy_create_edf_text, "%d", token->data.ival); return( yy_create_edf_text); case ENDLIST: return(")"); case ENDFILE: return("<end-of-file>"); default: /* must be keyword*/ if (mlines[0]) sprintf( yy_create_edf_text, "(%s", keywords[token->type]); else /* insert '(' */ { for (c1='(', pc=yy_create_edf_text; c1; c2= *pc, *pc++ =c1, c1=c2); *pc = '\0'; } return( yy_create_edf_text); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -