PageRenderTime 47ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/nesc-1.3.3/src/nesc-dfilter.c

#
C | 388 lines | 271 code | 62 blank | 55 comment | 29 complexity | f049e290865327014ca989c225eefe51 MD5 | raw file
Possible License(s): LGPL-2.0, LGPL-2.1, GPL-2.0, BSD-3-Clause, CC-BY-SA-3.0
  1. /* This file is part of the nesC compiler.
  2. Copyright (C) 2002 Intel Corporation
  3. The attached "nesC" software is provided to you under the terms and
  4. conditions of the GNU General Public License Version 2 as published by the
  5. Free Software Foundation.
  6. nesC is distributed in the hope that it will be useful,
  7. but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  9. GNU General Public License for more details.
  10. You should have received a copy of the GNU General Public License
  11. along with nesC; see the file COPYING. If not, write to
  12. the Free Software Foundation, 59 Temple Place - Suite 330,
  13. Boston, MA 02111-1307, USA. */
  14. #include <sys/types.h>
  15. #include <regex.h>
  16. #include <fnmatch.h>
  17. #include "parser.h"
  18. #include "nesc-dump.h"
  19. #include "nesc-dspec.h"
  20. #include "nesc-dspec-int.h"
  21. #include "nesc-semantics.h"
  22. /* Filters for XML dump requests. Current filters:
  23. file(globexp): match containing file name (unix-style file matching)
  24. name(regexp): match by item name (regular expression matching)
  25. attribute(namelist): match items containing one of the attributes
  26. in the namelist
  27. component(cname): match containing component name
  28. global(): match items from the global (C) scope
  29. instance(): match items in instances of generic components
  30. abstract(): match items that are not fully instantiated
  31. !global() && !abstract() && !instances(): "in a non-generic component"
  32. abstract() && !instance(): "in a generic component"
  33. !abstract() && instance(): "in a fully instantiated generic
  34. component (i.e., shows up in the generated C code)"
  35. abstract() && instance(): "a partially instantiated generic component,
  36. i.e., a generic component instantiated within a
  37. generic configuration"
  38. Filters can be combined with and, or, not.
  39. */
  40. /* Implementation of filters is OOish, see the filter_op structure.
  41. Filters can be applied to nesc/tag/data_declaration objects (separate
  42. method for each).
  43. Each filter has an argument specification string of the form:
  44. - a sequence of n and t's for token and int arguments (in order)
  45. - "*t" or "*n" for an arbitrary list of tokens or numbers.
  46. See check_arg, make_ndf_op to extend this.
  47. */
  48. static bool filter_file(ndf_op filter, location loc)
  49. {
  50. return !fnmatch(nd_tokenval(filter->args), loc->filename, 0);
  51. }
  52. static bool filter_name(ndf_op filter, const char *name)
  53. {
  54. return name && !regexec(filter->info, name, 0, NULL, 0);
  55. }
  56. static bool filter_attribute(ndf_op filter, dd_list/*nesc_attribute*/ attrs)
  57. {
  58. nd_arg reqattr;
  59. dd_list_pos actualattr;
  60. if (!attrs)
  61. return FALSE;
  62. /* return true if intersection of attributes in filter and attrs is
  63. non-empty */
  64. scan_nd_arg (reqattr, filter->args)
  65. {
  66. const char *reqname = nd_tokenval(reqattr);
  67. dd_scan (actualattr, attrs)
  68. {
  69. nesc_attribute a = DD_GET(nesc_attribute, actualattr);
  70. if (!strcmp(a->word1->cstring.data, reqname))
  71. return TRUE;
  72. }
  73. }
  74. return FALSE;
  75. }
  76. static bool filter_component(ndf_op filter, nesc_declaration container)
  77. {
  78. return container &&
  79. !strcmp(nd_tokenval(filter->args), container->instance_name);
  80. }
  81. static bool fddecl_file(ndf_op op, data_declaration ddecl)
  82. {
  83. return filter_file(op, ddecl->definition ? ddecl->definition->location : ddecl->ast->location);
  84. }
  85. static bool fndecl_file(ndf_op op, nesc_declaration ndecl)
  86. {
  87. return filter_file(op, ndecl->ast->location);
  88. }
  89. static bool ftdecl_file(ndf_op op, tag_declaration tdecl)
  90. {
  91. return tdecl->definition && filter_file(op, tdecl->definition->location);
  92. }
  93. static bool fddecl_attribute(ndf_op op, data_declaration ddecl)
  94. {
  95. return filter_attribute(op, ddecl->attributes);
  96. }
  97. static bool fndecl_attribute(ndf_op op, nesc_declaration ndecl)
  98. {
  99. return filter_attribute(op, ndecl->attributes);
  100. }
  101. static bool ftdecl_attribute(ndf_op op, tag_declaration tdecl)
  102. {
  103. return filter_attribute(op, tdecl->attributes);
  104. }
  105. static void fcompile_name(ndf_op op)
  106. {
  107. int err;
  108. op->info = ralloc(dump_region, regex_t);
  109. err = regcomp(op->info, nd_tokenval(op->args), REG_EXTENDED);
  110. if (err)
  111. {
  112. char errmsg[200];
  113. regerror(err, op->info, errmsg, sizeof errmsg);
  114. nderror(errmsg);
  115. }
  116. }
  117. static bool fddecl_name(ndf_op op, data_declaration ddecl)
  118. {
  119. return filter_name(op, ddecl->name);
  120. }
  121. static bool fndecl_name(ndf_op op, nesc_declaration ndecl)
  122. {
  123. return filter_name(op, ndecl->instance_name);
  124. }
  125. static bool ftdecl_name(ndf_op op, tag_declaration tdecl)
  126. {
  127. return filter_name(op, tdecl->name);
  128. }
  129. static bool fddecl_component(ndf_op op, data_declaration ddecl)
  130. {
  131. return filter_component(op, ddecl->container);
  132. }
  133. static bool fndecl_component(ndf_op op, nesc_declaration ndecl)
  134. {
  135. /* XXX: should this do something obvious w/ instantiated
  136. abstract components? */
  137. return FALSE;
  138. }
  139. static bool ftdecl_component(ndf_op op, tag_declaration tdecl)
  140. {
  141. return filter_component(op, tdecl->container);
  142. }
  143. static bool fddecl_global(ndf_op op, data_declaration ddecl)
  144. {
  145. return !ddecl->container && !ddecl->container_function;
  146. }
  147. static bool fndecl_global(ndf_op op, nesc_declaration ndecl)
  148. {
  149. /* XXX: see fndecl_component comment */
  150. return TRUE;
  151. }
  152. static bool ftdecl_global(ndf_op op, tag_declaration tdecl)
  153. {
  154. return !tdecl->container /* && !tdecl->container_function*/;
  155. }
  156. static bool is_instance(nesc_declaration ndecl)
  157. {
  158. return ndecl && ndecl->arguments;
  159. }
  160. static bool fddecl_instance(ndf_op op, data_declaration ddecl)
  161. {
  162. return is_instance(ddecl_container(ddecl));
  163. }
  164. static bool fndecl_instance(ndf_op op, nesc_declaration ndecl)
  165. {
  166. return is_instance(ndecl);
  167. }
  168. static bool ftdecl_instance(ndf_op op, tag_declaration tdecl)
  169. {
  170. return is_instance(tdecl_container(tdecl));
  171. }
  172. static bool is_abstract(nesc_declaration ndecl)
  173. {
  174. return ndecl && ndecl->abstract;
  175. }
  176. static bool fddecl_abstract(ndf_op op, data_declaration ddecl)
  177. {
  178. return is_abstract(ddecl_container(ddecl));
  179. }
  180. static bool fndecl_abstract(ndf_op op, nesc_declaration ndecl)
  181. {
  182. return is_abstract(ndecl);
  183. }
  184. static bool ftdecl_abstract(ndf_op op, tag_declaration tdecl)
  185. {
  186. return is_abstract(tdecl_container(tdecl));
  187. }
  188. static struct filter_op {
  189. const char *name;
  190. const char *args; /* Argument specification (see top) */
  191. /* (optional) filter "compilation" (eg for regexps) */
  192. void (*compile)(ndf_op op);
  193. /* Execute filter op on Xdecl */
  194. bool (*execute_ddecl)(ndf_op op, data_declaration ddecl);
  195. bool (*execute_ndecl)(ndf_op op, nesc_declaration ndecl);
  196. bool (*execute_tdecl)(ndf_op op, tag_declaration tdecl);
  197. } ops[] = {
  198. { "file", "t", NULL, fddecl_file, fndecl_file, ftdecl_file },
  199. { "name", "t", fcompile_name, fddecl_name, fndecl_name, ftdecl_name },
  200. { "component", "t", NULL, fddecl_component, fndecl_component, ftdecl_component },
  201. { "global", "", NULL, fddecl_global, fndecl_global, ftdecl_global },
  202. { "instance", "", NULL, fddecl_instance, fndecl_instance, ftdecl_instance },
  203. { "abstract", "", NULL, fddecl_abstract, fndecl_abstract, ftdecl_abstract },
  204. { "attribute", "*t", NULL, fddecl_attribute, fndecl_attribute, ftdecl_attribute }
  205. };
  206. static void check_arg(nd_arg arg, int kind)
  207. {
  208. bool ok;
  209. switch (kind)
  210. {
  211. default: ok = TRUE;
  212. case 't': ok = is_nd_token(arg); break;
  213. case 'n': ok = is_nd_int(arg); break;
  214. }
  215. if (!ok)
  216. nderror("wrong argument type");
  217. }
  218. nd_filter make_ndf_op(region r, const char *name, nd_arg args)
  219. {
  220. int nargs = nd_arg_length(args);
  221. ndf_op op = new_ndf_op(r, name, args, nargs);
  222. int i;
  223. for (i = 0; i < sizeof ops / sizeof *ops; i++)
  224. if (!strcmp(name, ops[i].name))
  225. {
  226. const char *argspec = ops[i].args;
  227. nd_arg arg;
  228. int old_ec = errorcount;
  229. op->filter_index = i;
  230. /* Check arguments */
  231. if (argspec[0] == '*')
  232. scan_nd_arg (arg, args)
  233. check_arg(arg, argspec[1]);
  234. else
  235. {
  236. scan_nd_arg (arg, args)
  237. {
  238. if (!*argspec)
  239. nderror("too many arguments");
  240. else
  241. check_arg(arg, *argspec++);
  242. }
  243. if (*argspec)
  244. nderror("not enough arguments");
  245. }
  246. if (errorcount == old_ec && ops[i].compile)
  247. ops[i].compile(op);
  248. return CAST(nd_filter, op);
  249. }
  250. nderror("unknown filter operator");
  251. return CAST(nd_filter, op);
  252. }
  253. /* The current filter, applied by dump_filter_Xdecl */
  254. static nd_filter current_filter;
  255. enum { filter_ddecl, filter_ndecl, filter_tdecl };
  256. static bool dofilter(int op, nd_filter f, void *decl)
  257. {
  258. switch (f->kind)
  259. {
  260. case kind_ndf_and: {
  261. ndf_and f1 = CAST(ndf_and, f);
  262. return dofilter(op, f1->filter1, decl) && dofilter(op, f1->filter2, decl);
  263. }
  264. case kind_ndf_or: {
  265. ndf_or f1 = CAST(ndf_or, f);
  266. return dofilter(op, f1->filter1, decl) || dofilter(op, f1->filter2, decl);
  267. }
  268. case kind_ndf_not: {
  269. ndf_not f1 = CAST(ndf_not, f);
  270. return !dofilter(op, f1->filter1, decl);
  271. }
  272. case kind_ndf_op: {
  273. ndf_op f1 = CAST(ndf_op, f);
  274. struct filter_op *fop = &ops[f1->filter_index];
  275. switch (op)
  276. {
  277. case filter_ddecl: return fop->execute_ddecl(f1, decl);
  278. case filter_ndecl: return fop->execute_ndecl(f1, decl);
  279. case filter_tdecl: return fop->execute_tdecl(f1, decl);
  280. default: assert(0); return FALSE;
  281. }
  282. }
  283. default:
  284. assert(0); return FALSE;
  285. }
  286. }
  287. bool dump_filter_ddecl(data_declaration ddecl)
  288. {
  289. return !current_filter || dofilter(filter_ddecl, current_filter, ddecl);
  290. }
  291. bool dump_filter_ndecl(nesc_declaration ndecl)
  292. {
  293. return !current_filter || dofilter(filter_ndecl, current_filter, ndecl);
  294. }
  295. bool dump_filter_tdecl(tag_declaration tdecl)
  296. {
  297. return !current_filter || dofilter(filter_tdecl, current_filter, tdecl);
  298. }
  299. void dump_set_filter(nd_option opt)
  300. {
  301. nd_arg *optargs = &opt->args;
  302. nd_filter extracted = NULL;
  303. /* Extract filters from opt, build current filter. If multiple filters,
  304. just and them together. */
  305. while (*optargs)
  306. if (!is_nd_filter(*optargs))
  307. optargs = &(*optargs)->next;
  308. else
  309. {
  310. nd_filter f = CAST(nd_filter, *optargs);
  311. *optargs = (*optargs)->next;
  312. if (extracted)
  313. {
  314. ndf_and x = new_ndf_and(dump_region, extracted, f);
  315. extracted = CAST(nd_filter, x);
  316. }
  317. else
  318. extracted = f;
  319. }
  320. current_filter = extracted;
  321. }