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

📄 preproc.c

📁 开源的nasm编译器源码,研究编译器原理很有帮且
💻 C
📖 第 1 页 / 共 5 页
字号:
	    fname++;	fnlen = strcspn(fname, "\"");	line = nasm_malloc(20 + fnlen);	sprintf(line, "%%line %d %.*s", lineno, fnlen, fname);	nasm_free(oldline);    }    if (tasm_compatible_mode)	return check_tasm_directive(line);    return line;}/* * The hash function for macro lookups. Note that due to some * macros having case-insensitive names, the hash function must be * invariant under case changes. We implement this by applying a * perfectly normal hash function to the uppercase of the string. */static inthash(char *s){    unsigned int h = 0;    int i = 0;    /*     * Powers of three, mod 31.     */    static const int multipliers[] = {	1, 3, 9, 27, 19, 26, 16, 17, 20, 29, 25, 13, 8, 24, 10,	30, 28, 22, 4, 12, 5, 15, 14, 11, 2, 6, 18, 23, 7, 21    };    while (*s)    {	h += multipliers[i] * (unsigned char) (toupper(*s));	s++;	if (++i >= elements(multipliers))	    i = 0;    }    h %= NHASH;    return h;}/* * Free a linked list of tokens. */static voidfree_tlist(Token * list){    while (list)    {	list = delete_Token(list);    }}/* * Free a linked list of lines. */static voidfree_llist(Line * list){    Line *l;    while (list)    {	l = list;	list = list->next;	free_tlist(l->first);	nasm_free(l);    }}/* * Free an MMacro */static voidfree_mmacro(MMacro * m){    nasm_free(m->name);    free_tlist(m->dlist);    nasm_free(m->defaults);    free_llist(m->expansion);    nasm_free(m);}/* * Pop the context stack. */static voidctx_pop(void){    Context *c = cstk;    SMacro *smac, *s;    cstk = cstk->next;    smac = c->localmac;    while (smac)    {	s = smac;	smac = smac->next;	nasm_free(s->name);	free_tlist(s->expansion);	nasm_free(s);    }    nasm_free(c->name);    nasm_free(c);}#define BUF_DELTA 512/* * Read a line from the top file in istk, handling multiple CR/LFs * at the end of the line read, and handling spurious ^Zs. Will * return lines from the standard macro set if this has not already * been done. */static char *read_line(void){    char *buffer, *p, *q;    int bufsize, continued_count;    if (stdmacpos)    {	if (*stdmacpos)	{	    char *ret = nasm_strdup(*stdmacpos++);	    if (!*stdmacpos && any_extrastdmac)	    {		stdmacpos = extrastdmac;		any_extrastdmac = FALSE;		return ret;	    }	    /*	     * Nasty hack: here we push the contents of `predef' on	     * to the top-level expansion stack, since this is the	     * most convenient way to implement the pre-include and	     * pre-define features.	     */	    if (!*stdmacpos)	    {		Line *pd, *l;		Token *head, **tail, *t;		for (pd = predef; pd; pd = pd->next)		{		    head = NULL;		    tail = &head;		    for (t = pd->first; t; t = t->next)		    {			*tail = new_Token(NULL, t->type, t->text, 0);			tail = &(*tail)->next;		    }		    l = nasm_malloc(sizeof(Line));		    l->next = istk->expansion;		    l->first = head;		    l->finishes = FALSE;		    istk->expansion = l;		}	    }	    return ret;	}	else	{	    stdmacpos = NULL;	}    }    bufsize = BUF_DELTA;    buffer = nasm_malloc(BUF_DELTA);    p = buffer;    continued_count = 0;    while (1)    {	q = fgets(p, bufsize - (p - buffer), istk->fp);	if (!q)	    break;	p += strlen(p);	if (p > buffer && p[-1] == '\n')	{           /* Convert backslash-CRLF line continuation sequences into              nothing at all (for DOS and Windows) */           if (((p - 2) > buffer) && (p[-3] == '\\') && (p[-2] == '\r')) {               p -= 3;               *p = 0;               continued_count++;           }           /* Also convert backslash-LF line continuation sequences into              nothing at all (for Unix) */           else if (((p - 1) > buffer) && (p[-2] == '\\')) {               p -= 2;               *p = 0;               continued_count++;           }           else {               break;           }	}	if (p - buffer > bufsize - 10)	{	    long offset = p - buffer;	    bufsize += BUF_DELTA;	    buffer = nasm_realloc(buffer, bufsize);	    p = buffer + offset;	/* prevent stale-pointer problems */	}    }    if (!q && p == buffer)    {	nasm_free(buffer);	return NULL;    }    src_set_linnum(src_get_linnum() + istk->lineinc + (continued_count * istk->lineinc));    /*     * Play safe: remove CRs as well as LFs, if any of either are     * present at the end of the line.     */    while (--p >= buffer && (*p == '\n' || *p == '\r'))	*p = '\0';    /*     * Handle spurious ^Z, which may be inserted into source files     * by some file transfer utilities.     */    buffer[strcspn(buffer, "\032")] = '\0';    list->line(LIST_READ, buffer);    return buffer;}/* * Tokenise a line of text. This is a very simple process since we * don't need to parse the value out of e.g. numeric tokens: we * simply split one string into many. */static Token *tokenise(char *line){    char *p = line;    int type;    Token *list = NULL;    Token *t, **tail = &list;    while (*line)    {	p = line;	if (*p == '%')	{		p++;		if ( isdigit(*p) ||			((*p == '-' || *p == '+') && isdigit(p[1])) ||			((*p == '+') && (isspace(p[1]) || !p[1])))				{			do			{			p++;			}			while (isdigit(*p));			type = TOK_PREPROC_ID;		}		else if (*p == '{')		{			p++;			while (*p && *p != '}')			{			p[-1] = *p;			p++;			}			p[-1] = '\0';			if (*p)			p++;			type = TOK_PREPROC_ID;		}		else if (isidchar(*p) ||				((*p == '!' || *p == '%' || *p == '$') &&					isidchar(p[1])))		{			do			{			p++;			}			while (isidchar(*p));			type = TOK_PREPROC_ID;		}		else		{			type = TOK_OTHER;			if (*p == '%')				p++;		}	}	else if (isidstart(*p) || (*p == '$' && isidstart(p[1])))	{	    type = TOK_ID;	    p++;	    while (*p && isidchar(*p))		p++;	}	else if (*p == '\'' || *p == '"')	{	    /*	     * A string token.	     */	    char c = *p;	    p++;	    type = TOK_STRING;	    while (*p && *p != c)		p++;	    if (*p)	    {		p++;	    }	    else	    {		error(ERR_WARNING, "unterminated string");	    }	}	else if (isnumstart(*p))	{	    /*	     * A number token.	     */	    type = TOK_NUMBER;	    p++;	    while (*p && isnumchar(*p))		p++;	}	else if (isspace(*p))	{	    type = TOK_WHITESPACE;	    p++;	    while (*p && isspace(*p))		p++;	    /*	     * Whitespace just before end-of-line is discarded by	     * pretending it's a comment; whitespace just before a	     * comment gets lumped into the comment.	     */	    if (!*p || *p == ';')	    {		type = TOK_COMMENT;		while (*p)		    p++;	    }	}	else if (*p == ';')	{	    type = TOK_COMMENT;	    while (*p)		p++;	}	else	{	    /*	     * Anything else is an operator of some kind. We check	     * for all the double-character operators (>>, <<, //,	     * %%, <=, >=, ==, !=, <>, &&, ||, ^^), but anything	     * else is a single-character operator.	     */	    type = TOK_OTHER;	    if ((p[0] == '>' && p[1] == '>') ||		    (p[0] == '<' && p[1] == '<') ||		    (p[0] == '/' && p[1] == '/') ||		    (p[0] == '<' && p[1] == '=') ||		    (p[0] == '>' && p[1] == '=') ||		    (p[0] == '=' && p[1] == '=') ||		    (p[0] == '!' && p[1] == '=') ||		    (p[0] == '<' && p[1] == '>') ||		    (p[0] == '&' && p[1] == '&') ||		    (p[0] == '|' && p[1] == '|') ||		    (p[0] == '^' && p[1] == '^'))	    {		p++;	    }	    p++;	}	if (type != TOK_COMMENT)	{	    *tail = t = new_Token(NULL, type, line, p - line);	    tail = &t->next;	}	line = p;    }    return list;}/* * this function allocates a new managed block of memory and * returns a pointer to the block.  The managed blocks are  * deleted only all at once by the delete_Blocks function. */static void *new_Block(size_t size){	Blocks *b = &blocks;		/* first, get to the end of the linked list	 */	while (b->next)		b = b->next;	/* now allocate the requested chunk */	b->chunk = nasm_malloc(size);		/* now allocate a new block for the next request */	b->next = nasm_malloc(sizeof(Blocks));	/* and initialize the contents of the new block */	b->next->next = NULL;	b->next->chunk = NULL;	return b->chunk;}/* * this function deletes all managed blocks of memory */static voiddelete_Blocks(void){	Blocks *a,*b = &blocks;	/* 	 * keep in mind that the first block, pointed to by blocks	 * is a static and not dynamically allocated, so we don't 	 * free it.	 */	while (b)	{		if (b->chunk)			nasm_free(b->chunk);		a = b;		b = b->next;                if (a != &blocks)			nasm_free(a);	}}	/* *  this function creates a new Token and passes a pointer to it  *  back to the caller.  It sets the type and text elements, and *  also the mac and next elements to NULL. */static Token *new_Token(Token * next, int type, char *text, int txtlen){    Token *t;    int i;    if (freeTokens == NULL)    {	freeTokens = (Token *)new_Block(TOKEN_BLOCKSIZE * sizeof(Token));	for (i = 0; i < TOKEN_BLOCKSIZE - 1; i++)	    freeTokens[i].next = &freeTokens[i + 1];	freeTokens[i].next = NULL;    }    t = freeTokens;    freeTokens = t->next;    t->next = next;    t->mac = NULL;    t->type = type;    if (type == TOK_WHITESPACE || text == NULL)    {	t->text = NULL;    }    else    {	if (txtlen == 0)	    txtlen = strlen(text);	t->text = nasm_malloc(1 + txtlen);	strncpy(t->text, text, txtlen);	t->text[txtlen] = '\0';    }    return t;}static Token *delete_Token(Token * t){    Token *next = t->next;    nasm_free(t->text);    t->next = freeTokens;    freeTokens = t;    return next;}/* * Convert a line of tokens back into text. * If expand_locals is not zero, identifiers of the form "%$*xxx" * will be transformed into ..@ctxnum.xxx */static char *detoken(Token * tlist, int expand_locals){    Token *t;    int len;    char *line, *p;    len = 0;    for (t = tlist; t; t = t->next)    {	if (t->type == TOK_PREPROC_ID && t->text[1] == '!')	{	    char *p = getenv(t->text + 2);	    nasm_free(t->text);	    if (p)		t->text = nasm_strdup(p);	    else		t->text = NULL;	}	/* Expand local macros here and not during preprocessing */	if (expand_locals &&		t->type == TOK_PREPROC_ID && t->text &&		t->text[0] == '%' && t->text[1] == '$')	{	    Context *ctx = get_ctx(t->text, FALSE);	    if (ctx)	    {		char buffer[40];		char *p, *q = t->text + 2;		q += strspn(q, "$");		sprintf(buffer, "..@%lu.", ctx->number);		p = nasm_strcat(buffer, q);		nasm_free(t->text);		t->text = p;	    }	}	if (t->type == TOK_WHITESPACE)	{	    len++;

⌨️ 快捷键说明

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