📄 func.c
字号:
/*
Copyright 1994-2003 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
This program is derived from the cc68k complier by
Matthew Brandt (mattb@walkingdog.net)
You may contact the author of this derivative at:
mailto::camille@bluegrass.net
or by snail mail at:
David Lindauer
850 Washburn Ave Apt 99
Louisville, KY 40222
*/
#include <stdio.h>
#include <string.h>
#include "lists.h"
#include "expr.h"
#include "c.h"
#include "ccerr.h"
extern int prm_c99;
extern int stdpragmas;
extern LIST *local_using_list, *local_tag_using_list;
extern char *templatePrefix;
extern int mainfunc;
extern int lineno;
extern SNODE *cbautoinithead, *cbautoinittail;
extern int ispascal, isstdcall;
extern FILE *listFile;
extern enum e_sym lastst;
extern long firstlabel, nextlabel;
extern char lastid[];
extern TABLE *gsyms, lsyms, ltags;
extern int global_flag;
extern int stdaddrsize, stdretblocksize;
extern int stackadd, stackmod;
extern TYP *head, *tail, **headptr;
extern char declid[100];
extern int prm_listfile;
extern int prm_cplusplus, prm_debug;
extern int stdintsize;
extern int goodcode;
extern int prm_linkreg;
extern TABLE lsyms;
extern int total_errors;
extern int cppflags;
extern SYM *declclass, *typequal;
extern int prm_cmangle;
extern LASTDEST *lastDestPointer;
extern int conscount;
extern int prm_xcept;
extern TRYBLOCK *try_block_list;
typedef struct _dlist {
struct _dlist *fwd, *back ;
void *data, *current ;
} DLIST ;
DLIST *gotoList ;
int gotoCount;
int block_nesting, arg_nesting;
int infuncargs, infunclineno;
int funcnesting;
ENODE *block_rundown; /* maintains destructors for block, WILL maintain global
* scope when no funcs in progress but we don't use that
* now
*/
TABLE oldlsym, oldltag;
LIST *varlisthead, *varlisttail;
LIST *instantiated_inlines;
SNODE *funcstmt, *funcendstmt;
static int skm_func[] =
{
closepa, begin, semicolon, 0
};
SYM *currentfunc = 0, *lastfunc;
/* function compilation routines */
void funcini(void)
{
currentfunc = lastfunc = 0;
infuncargs = 0;
funcnesting = 0;
instantiated_inlines = 0;
}
//-------------------------------------------------------------------------
void declfuncarg(int isint, int isfar, SYM *sp)
{
char *names[50]; /* 50 parameters maximum */
int nparms, poffset, i, isinline;
SYM *sp1, *sp2, *spsave[50], *oldargs = 0, *typesp = typequal;
TYP *temp, *temp1, *todo, *oheadptr;
char oldeclare[100];
char *nm;
sp->hasproto = TRUE;
if (!infuncargs)
{
if (lineno != infunclineno)
funcstmt = snp_line(FALSE);
// only want the first one
infunclineno = lineno;
}
infuncargs++;
if (prm_linkreg && !isint)
{
poffset = stdretblocksize; /* size of return block */
if (isfar)
poffset += stdintsize;
}
else
poffset = 0;
/* size of return block */
nparms = 0;
temp = head;
temp1 = tail;
oheadptr = headptr;
todo = sp->tp;
if (!prm_cplusplus)
{
sp2 = gsearch(declid);
if (sp2)
{
oldargs = sp2->tp->lst.head;
}
}
todo->lst.head = todo->lst.tail = 0;
if (lastst == kw_void)
{
getsym();
if (lastst != closepa)
{
backup(lastst);
lastst = kw_void;
}
else
{
todo->lst.head = (SYM*) - 1;
getsym();
goto verify;
}
}
else
if (lastst == closepa)
{
if (prm_cplusplus)
todo->lst.head = (SYM*) - 1;
getsym();
goto verify;
} else
if (lastst == id)
{
if ((typesp = typesearch(lastid)) && (typesp->storage_class ==
sc_type))
if (typesp->tp->type == bt_void)
{
getsym();
if (lastst != closepa)
{
backup(lastst);
lastst = id;
}
else
{
todo->lst.head = (SYM*) - 1;
getsym();
goto verify;
}
}
}
strcpy(oldeclare, declid);
if (!prm_cplusplus && lastst == id && ((sp1 = search(lastid, gsyms)) == 0
|| sp1->storage_class != sc_type) && ((sp1 = search(lastid, &lsyms)) ==
0 || sp1->storage_class != sc_type))
{
int xglob = global_flag;
/* declare parameters */
global_flag = 0;
while (lastst == id)
{
names[nparms++] = litlate(lastid);
getsym();
if (lastst == comma)
getsym();
else
break;
}
needpunc(closepa, skm_func);
sp->oldstyle = xalloc((nparms + 1) *sizeof(char*));
sp->oldstyle[0] = nparms;
memcpy(&sp->oldstyle[1], names, nparms *sizeof(char*));
global_flag = xglob;
if (prm_debug)
debug_outfunc(sp);
infuncargs--;
return ;
}
else
{
SYM *tq = typequal;
doargdecl(sc_member, names, &nparms, &todo->lst, isinline = TRUE);
needpunc(closepa, skm_func);
replaceTemplateFunctionClasses(sp, tq);
}
strcpy(declid, oldeclare);
if (!ispascal && isstructured(todo->btp))
{
poffset += stdaddrsize;
sp->calleenearret = TRUE;
}
typequal = 0;
for (i = 0; i < nparms; ++i)
{
if ((sp1 = search(names[i], &todo->lst)) == 0)
sp1 = makeint(litlate(names[i]), &todo->lst);
if (sp1->tp)
sp1->tp->uflags |= UF_DEFINED;
sp1->funcparm = TRUE;
spsave[i] = sp1;
sp1->storage_class = sc_auto;
}
typequal = typesp;
/*
* parameter allocation. Have to do things backwards if this
* function has the pascal declarator
*/
if (!ispascal)
for (i = 0; i < nparms; ++i)
{
sp1 = spsave[i];
if (sp1->tp->type != bt_pointer && sp1->tp->type != bt_farpointer &&
sp1->tp->type != bt_segpointer && sp1->tp->size < stdintsize)
{
sp1->value.i = poffset + funcvaluesize(sp1->tp->size);
poffset += stdintsize;
}
else
{
sp1->value.i = poffset;
if (sp1->tp->type == bt_pointer)
{
TYP *tp = sp1->tp;
if (!(tp->val_flag &VARARRAY))
tp = tp->btp;
if (tp->type != bt_pointer || !(tp->val_flag &VARARRAY))
poffset += stdaddrsize;
else
{
poffset += tp->size;
}
}
else
poffset += sp1->tp->size;
if (poffset % stdintsize)
poffset += stdintsize - poffset % stdintsize;
}
}
else
for (i = nparms - 1; i >= 0; --i)
{
sp1 = spsave[i];
if (sp1->tp->type != bt_pointer && sp1->tp->type != bt_farpointer &&
sp1->tp->type != bt_segpointer && sp1->tp->size < stdintsize)
{
sp1->value.i = poffset + funcvaluesize(sp1->tp->size);
poffset += stdintsize;
}
else
{
sp1->value.i = poffset;
if (sp1->tp->type == bt_pointer)
{
TYP *tp = sp1->tp;
if (!(tp->val_flag &VARARRAY))
tp = tp->btp;
if (tp->type != bt_pointer || !(tp->val_flag &VARARRAY))
poffset += stdaddrsize;
else
{
poffset += tp->size;
}
}
else
poffset += sp1->tp->size;
if (poffset % stdintsize)
poffset += stdintsize - poffset % stdintsize;
}
}
sp->paramsize = poffset;
if (!isinline)
{
todo->lst.head = todo->lst.tail = 0;
for (i = 0; i < nparms; i++)
insert(spsave[i], &todo->lst);
}
sp->recalculateParameters = TRUE;
if (prm_cplusplus && todo->lst.head == 0)
todo->lst.head = (SYM*) - 1;
/* () is equiv to (void) in cpp */
verify: head = temp;
tail = temp1;
headptr = oheadptr;
if (prm_debug)
debug_outfunc(sp);
if (prm_cplusplus)
{
infuncargs--;
return ;
}
if (oldargs && head->lst.head)
{
SYM *newargs = head->lst.head;
while (oldargs && newargs)
{
if (oldargs == (SYM*) - 1 || newargs == (SYM*) - 1)
break;
if (!exactype(oldargs->tp, newargs->tp, FALSE))
gensymerror(ERR_DECLMISMATCH, sp2->name);
oldargs = oldargs->next;
newargs = newargs->next;
}
if (oldargs && oldargs != (SYM*) - 1)
gensymerror(ERR_ARGLENSHORT, sp->name);
if (newargs && newargs != (SYM*) - 1)
gensymerror(ERR_ARGLENLONG, sp->name);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -