2 * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
3 * See the copyright notice in the ACK home directory, in the file "Copyright".
5 /* $Id: checkargs.c,v 1.7 1994/06/24 12:25:28 ceriel Exp $ */
7 /******** A R G U M E N T T Y P E C H E C K I N G ********/
12 extern char *strcpy();
14 #define streq(s1,s2) (strcmp(s1, s2) == 0)
16 /* a format is developed into a normal parameter definition */
17 PRIVATE int is_formatargs; /* present or not */
18 PRIVATE char formatargs[1000]; /* the definitions */
21 PRIVATE char *next_argtype();
22 PRIVATE int type_match();
24 PRIVATE conv_format();
30 return streq(act, form)
31 || streq(act, "erroneous")
32 || streq(form, "erroneous");
36 struct inpdef *id, *def;
38 char *act_tp = id->id_argtps;
39 int nrargs = 0; /* number of args */
41 /* void is a special case */
42 if ( /* the definition has one void argument */
43 def->id_nrargs == 1 && streq(def->id_argtps, "void:")
44 && /* the referent has no argumants */
46 ) /* we have a prefect match */
52 /* check normal arguments */
53 chk_argtps(id, def, &nrargs, act_tp, def->id_argtps);
56 /* there was a format */
59 /* skip over the actuals already covered */
60 for (i = 0; i < nrargs; i++) {
61 act_tp = next_argtype(act_tp);
64 /* and check the format arguments */
65 chk_argtps(id, (struct inpdef *)0, &nrargs,
66 act_tp, &formatargs[0]);
70 PRIVATE chk_argtps(id, def, nrargs, act_tp, form_tp)
71 struct inpdef *id; /* the actual call */
72 struct inpdef *def; /* 0 for format-derived definition */
73 int *nrargs; /* in-out parameter, counting */
74 char *act_tp; /* actual types */
75 char *form_tp; /* formal type definitions */
77 while (*act_tp && *form_tp && *form_tp != '.') {
78 register char *act_start = act_tp;
79 register char *form_start = form_tp;
81 /* isolate actual argument type */
82 act_tp = next_argtype(act_tp);
85 /* isolate formal argument type */
86 form_tp = next_argtype(form_tp);
90 if (!type_match(id, act_start, form_start)) {
94 form_type(act_form, act_start);
95 form_type(form_form, form_start);
96 report("%L: arg %d of %s (%s) differs from that in %L (%s)",
97 id, *nrargs, id->id_name,
98 act_form, def, form_form);
104 if (*form_tp == '.') /* ellipsis */
108 /* formal type definitions not exhausted */
109 report("%L: %s has fewer arguments than in %L",
110 id, id->id_name, def);
113 /* actual types not exhausted */
114 if (def && def->id_nrargs < 0) {
115 /* the function had VARARGS */
118 report("%L: %s has more arguments than in %L",
119 id, id->id_name, def);
128 while (*tp && *tp != ':') {
138 PRIVATE type_match(id, act, form)
142 if (form[0] == '"' && act[0] == '"') {
143 conv_format(id, act, form);
147 if ( (form[0] == '"' && streq(act, "char*"))
148 || (act[0] == '"' && streq(form, "char*"))
153 if (type_equal(act, form))
157 /* a non-negative constant */
158 /* might be signed or unsigned */
159 if (type_equal(&act[1], form))
161 if ( strncmp(form, "unsigned ", strlen("unsigned ")) == 0
162 && type_equal(&act[1], &form[strlen("unsigned ")])
170 PRIVATE conv_format(id, act, form)
174 /* convert the actual format into a def-list, using the
175 formal format (form) as a map to convert from %X to type
177 register char *fmt = &formatargs[0];
183 /* find next conversion specification */
184 while (*act && *act != '%') {
195 /* process options */
196 if (*act && *act == '-') {
199 while (*act && ('0' <= *act && *act <= '9')) {
207 if (*act && *act == '.') {
210 while (*act && ('0' <= *act && *act <= '9')) {
221 register char *cs = act;
223 /* find next conversion mapping */
224 while (*map && *map != '%') {
228 /* we ran off the map */
229 report("%L: unknown conversion specification in format",
234 while (*map && *map != '=') {
235 register int match = 0;
238 while (*map && *map != ']') {
246 match = (*map == *cs);
255 /* found the type belonging to %*cs */
256 while (*map && *map != '%' && *map != '"') {
268 PRIVATE form_type(buff, tp)
271 { /* store a formatted version of tp in buff
274 strcpy(buff, "char*");
276 else if (tp[0] == '+') {
277 sprintf(buff, "[unsigned] %s", &tp[1]);