macro.c
来自「基于4个mips核的noc设计」· C语言 代码 · 共 1,254 行 · 第 1/2 页
C
1,254 行
ptr = NULL; else ptr = (formal_entry *) hash_find (formal_hash, sb_terminate (t)); if (ptr) { if (ptr->actual.len) { sb_add_sb (out, &ptr->actual); } else { sb_add_sb (out, &ptr->def); } } else if (kind == '&') { /* Doing this permits people to use & in macro bodies. */ sb_add_char (out, '&'); } else if (copyifnotthere) { sb_add_sb (out, t); } else { sb_add_char (out, '\\'); sb_add_sb (out, t); } return src;}/* Expand the body of a macro. */static const char *macro_expand_body (in, out, formals, formal_hash, comment_char, locals) sb *in; sb *out; formal_entry *formals; struct hash_control *formal_hash; int comment_char; int locals;{ sb t; int src = 0; int inquote = 0; formal_entry *loclist = NULL; sb_new (&t); while (src < in->len) { if (in->ptr[src] == '&') { sb_reset (&t); if (macro_mri) { if (src + 1 < in->len && in->ptr[src + 1] == '&') src = sub_actual (src + 2, in, &t, formal_hash, '\'', out, 1); else sb_add_char (out, in->ptr[src++]); } else { /* FIXME: Why do we do this? */ src = sub_actual (src + 1, in, &t, formal_hash, '&', out, 0); } } else if (in->ptr[src] == '\\') { src++; if (in->ptr[src] == comment_char && comment_char != '\0') { /* This is a comment, just drop the rest of the line. */ while (src < in->len && in->ptr[src] != '\n') src++; } else if (in->ptr[src] == '(') { /* Sub in till the next ')' literally. */ src++; while (src < in->len && in->ptr[src] != ')') { sb_add_char (out, in->ptr[src++]); } if (in->ptr[src] == ')') src++; else return _("missplaced )"); } else if (in->ptr[src] == '@') { /* Sub in the macro invocation number. */ char buffer[10]; src++; sprintf (buffer, "%d", macro_number); sb_add_string (out, buffer); } else if (in->ptr[src] == '&') { /* This is a preprocessor variable name, we don't do them here. */ sb_add_char (out, '\\'); sb_add_char (out, '&'); src++; } else if (macro_mri && isalnum ((unsigned char) in->ptr[src])) { int ind; formal_entry *f; if (isdigit ((unsigned char) in->ptr[src])) ind = in->ptr[src] - '0'; else if (isupper ((unsigned char) in->ptr[src])) ind = in->ptr[src] - 'A' + 10; else ind = in->ptr[src] - 'a' + 10; ++src; for (f = formals; f != NULL; f = f->next) { if (f->index == ind - 1) { if (f->actual.len != 0) sb_add_sb (out, &f->actual); else sb_add_sb (out, &f->def); break; } } } else { sb_reset (&t); src = sub_actual (src, in, &t, formal_hash, '\'', out, 0); } } else if ((macro_alternate || macro_mri) && (isalpha ((unsigned char) in->ptr[src]) || in->ptr[src] == '_' || in->ptr[src] == '$') && (! inquote || ! macro_strip_at || (src > 0 && in->ptr[src - 1] == '@'))) { if (! locals || src + 5 >= in->len || strncasecmp (in->ptr + src, "LOCAL", 5) != 0 || ! ISWHITE (in->ptr[src + 5])) { sb_reset (&t); src = sub_actual (src, in, &t, formal_hash, (macro_strip_at && inquote) ? '@' : '\'', out, 1); } else { formal_entry *f; src = sb_skip_white (src + 5, in); while (in->ptr[src] != '\n' && in->ptr[src] != comment_char) { static int loccnt; char buf[20]; const char *err; f = (formal_entry *) xmalloc (sizeof (formal_entry)); sb_new (&f->name); sb_new (&f->def); sb_new (&f->actual); f->index = LOCAL_INDEX; f->next = loclist; loclist = f; src = get_token (src, in, &f->name); ++loccnt; sprintf (buf, "LL%04x", loccnt); sb_add_string (&f->actual, buf); err = hash_jam (formal_hash, sb_terminate (&f->name), f); if (err != NULL) return err; src = sb_skip_comma (src, in); } } } else if (comment_char != '\0' && in->ptr[src] == comment_char && src + 1 < in->len && in->ptr[src + 1] == comment_char && !inquote) { /* Two comment chars in a row cause the rest of the line to be dropped. */ while (src < in->len && in->ptr[src] != '\n') src++; } else if (in->ptr[src] == '"' || (macro_mri && in->ptr[src] == '\'')) { inquote = !inquote; sb_add_char (out, in->ptr[src++]); } else if (in->ptr[src] == '@' && macro_strip_at) { ++src; if (src < in->len && in->ptr[src] == '@') { sb_add_char (out, '@'); ++src; } } else if (macro_mri && in->ptr[src] == '=' && src + 1 < in->len && in->ptr[src + 1] == '=') { formal_entry *ptr; sb_reset (&t); src = get_token (src + 2, in, &t); ptr = (formal_entry *) hash_find (formal_hash, sb_terminate (&t)); if (ptr == NULL) { /* FIXME: We should really return a warning string here, but we can't, because the == might be in the MRI comment field, and, since the nature of the MRI comment field depends upon the exact instruction being used, we don't have enough information here to figure out whether it is or not. Instead, we leave the == in place, which should cause a syntax error if it is not in a comment. */ sb_add_char (out, '='); sb_add_char (out, '='); sb_add_sb (out, &t); } else { if (ptr->actual.len) { sb_add_string (out, "-1"); } else { sb_add_char (out, '0'); } } } else { sb_add_char (out, in->ptr[src++]); } } sb_kill (&t); while (loclist != NULL) { formal_entry *f; f = loclist->next; /* Setting the value to NULL effectively deletes the entry. We avoid calling hash_delete because it doesn't reclaim memory. */ hash_jam (formal_hash, sb_terminate (&loclist->name), NULL); sb_kill (&loclist->name); sb_kill (&loclist->def); sb_kill (&loclist->actual); free (loclist); loclist = f; } return NULL;}/* Assign values to the formal parameters of a macro, and expand the body. */static const char *macro_expand (idx, in, m, out, comment_char) int idx; sb *in; macro_entry *m; sb *out; int comment_char;{ sb t; formal_entry *ptr; formal_entry *f; int is_positional = 0; int is_keyword = 0; int narg = 0; const char *err; sb_new (&t); /* Reset any old value the actuals may have. */ for (f = m->formals; f; f = f->next) sb_reset (&f->actual); f = m->formals; while (f != NULL && f->index < 0) f = f->next; if (macro_mri) { /* The macro may be called with an optional qualifier, which may be referred to in the macro body as \0. */ if (idx < in->len && in->ptr[idx] == '.') { formal_entry *n; n = (formal_entry *) xmalloc (sizeof (formal_entry)); sb_new (&n->name); sb_new (&n->def); sb_new (&n->actual); n->index = QUAL_INDEX; n->next = m->formals; m->formals = n; idx = get_any_string (idx + 1, in, &n->actual, 1, 0); } } /* Peel off the actuals and store them away in the hash tables' actuals. */ idx = sb_skip_white (idx, in); while (idx < in->len && in->ptr[idx] != comment_char) { int scan; /* Look and see if it's a positional or keyword arg. */ scan = idx; while (scan < in->len && !ISSEP (in->ptr[scan]) && !(macro_mri && in->ptr[scan] == '\'') && (!macro_alternate && in->ptr[scan] != '=')) scan++; if (scan < in->len && !macro_alternate && in->ptr[scan] == '=') { is_keyword = 1; /* It's OK to go from positional to keyword. */ /* This is a keyword arg, fetch the formal name and then the actual stuff. */ sb_reset (&t); idx = get_token (idx, in, &t); if (in->ptr[idx] != '=') return _("confusion in formal parameters"); /* Lookup the formal in the macro's list. */ ptr = (formal_entry *) hash_find (m->formal_hash, sb_terminate (&t)); if (!ptr) return _("macro formal argument does not exist"); else { /* Insert this value into the right place. */ sb_reset (&ptr->actual); idx = get_any_string (idx + 1, in, &ptr->actual, 0, 0); if (ptr->actual.len > 0) ++narg; } } else { /* This is a positional arg. */ is_positional = 1; if (is_keyword) return _("can't mix positional and keyword arguments"); if (!f) { formal_entry **pf; int c; if (!macro_mri) return _("too many positional arguments"); f = (formal_entry *) xmalloc (sizeof (formal_entry)); sb_new (&f->name); sb_new (&f->def); sb_new (&f->actual); f->next = NULL; c = -1; for (pf = &m->formals; *pf != NULL; pf = &(*pf)->next) if ((*pf)->index >= c) c = (*pf)->index + 1; if (c == -1) c = 0; *pf = f; f->index = c; } sb_reset (&f->actual); idx = get_any_string (idx, in, &f->actual, 1, 0); if (f->actual.len > 0) ++narg; do { f = f->next; } while (f != NULL && f->index < 0); } if (! macro_mri) idx = sb_skip_comma (idx, in); else { if (in->ptr[idx] == ',') ++idx; if (ISWHITE (in->ptr[idx])) break; } } if (macro_mri) { char buffer[20]; sb_reset (&t); sb_add_string (&t, macro_strip_at ? "$NARG" : "NARG"); ptr = (formal_entry *) hash_find (m->formal_hash, sb_terminate (&t)); sb_reset (&ptr->actual); sprintf (buffer, "%d", narg); sb_add_string (&ptr->actual, buffer); } err = macro_expand_body (&m->sub, out, m->formals, m->formal_hash, comment_char, 1); if (err != NULL) return err; /* Discard any unnamed formal arguments. */ if (macro_mri) { formal_entry **pf; pf = &m->formals; while (*pf != NULL) { if ((*pf)->name.len != 0) pf = &(*pf)->next; else { sb_kill (&(*pf)->name); sb_kill (&(*pf)->def); sb_kill (&(*pf)->actual); f = (*pf)->next; free (*pf); *pf = f; } } } sb_kill (&t); macro_number++; return NULL;}/* Check for a macro. If one is found, put the expansion into *EXPAND. COMMENT_CHAR is the comment character--this is used by gasp. Return 1 if a macro is found, 0 otherwise. */intcheck_macro (line, expand, comment_char, error, info) const char *line; sb *expand; int comment_char; const char **error; macro_entry **info;{ const char *s; char *copy, *cs; macro_entry *macro; sb line_sb; if (! isalpha ((unsigned char) *line) && *line != '_' && *line != '$' && (! macro_mri || *line != '.')) return 0; s = line + 1; while (isalnum ((unsigned char) *s) || *s == '_' || *s == '$') ++s; copy = (char *) alloca (s - line + 1); memcpy (copy, line, s - line); copy[s - line] = '\0'; for (cs = copy; *cs != '\0'; cs++) if (isupper ((unsigned char) *cs)) *cs = tolower (*cs); macro = (macro_entry *) hash_find (macro_hash, copy); if (macro == NULL) return 0; /* Wrap the line up in an sb. */ sb_new (&line_sb); while (*s != '\0' && *s != '\n' && *s != '\r') sb_add_char (&line_sb, *s++); sb_new (expand); *error = macro_expand (0, &line_sb, macro, expand, comment_char); sb_kill (&line_sb); /* Export the macro information if requested. */ if (info) *info = macro; return 1;}/* Delete a macro. */voiddelete_macro (name) const char *name;{ hash_delete (macro_hash, name);}/* Handle the MRI IRP and IRPC pseudo-ops. These are handled as a combined macro definition and execution. This returns NULL on success, or an error message otherwise. */const char *expand_irp (irpc, idx, in, out, get_line, comment_char) int irpc; int idx; sb *in; sb *out; int (*get_line) PARAMS ((sb *)); int comment_char;{ const char *mn; sb sub; formal_entry f; struct hash_control *h; const char *err; if (irpc) mn = "IRPC"; else mn = "IRP"; idx = sb_skip_white (idx, in); sb_new (&sub); if (! buffer_and_nest (mn, "ENDR", &sub, get_line)) return _("unexpected end of file in irp or irpc"); sb_new (&f.name); sb_new (&f.def); sb_new (&f.actual); idx = get_token (idx, in, &f.name); if (f.name.len == 0) return _("missing model parameter"); h = hash_new (); err = hash_jam (h, sb_terminate (&f.name), &f); if (err != NULL) return err; f.index = 1; f.next = NULL; sb_reset (out); idx = sb_skip_comma (idx, in); if (idx >= in->len || in->ptr[idx] == comment_char) { /* Expand once with a null string. */ err = macro_expand_body (&sub, out, &f, h, comment_char, 0); if (err != NULL) return err; } else { if (irpc && in->ptr[idx] == '"') ++idx; while (idx < in->len && in->ptr[idx] != comment_char) { if (!irpc) idx = get_any_string (idx, in, &f.actual, 1, 0); else { if (in->ptr[idx] == '"') { int nxt; nxt = sb_skip_white (idx + 1, in); if (nxt >= in->len || in->ptr[nxt] == comment_char) { idx = nxt; break; } } sb_reset (&f.actual); sb_add_char (&f.actual, in->ptr[idx]); ++idx; } err = macro_expand_body (&sub, out, &f, h, comment_char, 0); if (err != NULL) return err; if (!irpc) idx = sb_skip_comma (idx, in); else idx = sb_skip_white (idx, in); } } hash_die (h); sb_kill (&sub); return NULL;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?