source: git/modules/tools/misc.cc @ 4e859f5

spielwiese
Last change on this file since 4e859f5 was 4e859f5, checked in by Kai Krüger <krueger@…>, 25 years ago
major internal changes of handling definition git-svn-id: file:///usr/local/Singular/svn/trunk@2968 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 18.0 KB
Line 
1/****************************************
2*  Computer Algebra System SINGULAR     *
3****************************************/
4/* $Id: misc.cc,v 1.4 1999-03-24 13:04:20 krueger Exp $ */
5/*
6* ABSTRACT: lib parsing
7*/
8
9#include <mod2.h>
10#include <febase.h>
11#include <grammar.h>
12#include <ipid.h>
13#include <ipshell.h>
14#include <mmemory.h>
15#include <structs.h>
16#include <subexpr.h>
17#include <tok.h>
18#include <regex.h>
19
20#include "modgen.h"
21#include "typmap.h"
22
23#define NEW_PARAM 1
24
25#define SYSTYP_NONE   0
26#define SYSTYP_LINUX  1
27#define SYSTYP_HPUX9  2
28#define SYSTYP_HPUX10 3
29
30#if 0
31#  define logx printf
32#else
33#  define logx
34#endif
35
36char *DYNAinclude[] = {
37   "",
38   "#include <dlfcn.h>",
39   "#include <dl.h>",
40   "#include <dl.h>",
41   "#include <>",
42   "#include <>",
43   "#include <>",
44   NULL
45};
46
47int systyp = SYSTYP_NONE;
48
49BOOLEAN    expected_parms;
50int        cmdtok;
51BOOLEAN siq=FALSE;
52char *lastreserved=NULL;
53#define SELF_CMD MAX_TOK+1
54
55void enter_id(FILE *fp, char *name, char *value);
56void mod_write_enter_id(FILE *fp);
57
58
59/*=============== types =====================*/
60struct sValCmdTab
61{
62  short cmd;
63  short start;
64};
65
66#include "iparith.inc"
67
68/*=================== general utilities ============================*/
69int IsCmd(char *n, int & tok)
70{
71  int an=1;
72  int i,v;
73  int en=LAST_IDENTIFIER;
74 
75  if( strcmp(n, "SELF") == 0) {
76    tok = SELF_CMD;
77    return tok;
78  }
79 
80  loop
81  {
82    if(an>=en-1)
83    {
84      if (strcmp(n, cmds[an].name) == 0)
85      {
86        i=an;
87        break;
88      }
89      else if (strcmp(n, cmds[en].name) == 0)
90      {
91        i=en;
92        break;
93      }
94      else
95      {
96        return 0;
97      }
98    }
99    i=(an+en)/2;
100    v=strcmp(n,cmds[i].name);
101    if(v<0)
102    {
103      en=i;
104    }
105    else if(v>0)
106    {
107      an=i;
108    }
109    else /*v==0*/
110    {
111      break;
112    }
113  }
114  lastreserved=cmds[i].name;
115  tok=cmds[i].tokval;
116  if(cmds[i].alias==2)
117  {
118    printf("outdated identifier `%s` used - please change your code",
119    cmds[i].name);
120    cmds[i].alias=1;
121  }
122#if 0
123  if (!expected_parms)
124  {
125    switch (tok)
126    {
127      case IDEAL_CMD:
128      case INT_CMD:
129      case INTVEC_CMD:
130      case MAP_CMD:
131      case MATRIX_CMD:
132      case MODUL_CMD:
133      case POLY_CMD:
134      case PROC_CMD:
135      case RING_CMD:
136      case STRING_CMD:
137        cmdtok = tok;
138        break;
139    }
140  }
141#endif
142  logx("IsCmd: [%d] %s\n", tok, n);
143 
144  if( (cmds[i].toktype==ROOT_DECL) ||
145      (cmds[i].toktype==ROOT_DECL_LIST) ||
146      (cmds[i].toktype==RING_DECL) ||
147      ((cmds[i].toktype>=DRING_CMD) && (cmds[i].toktype<=VECTOR_CMD))) 
148    return cmds[i].toktype;
149  return 0;
150}
151
152char * decl2str(int n, char *name)
153{
154  switch(n)
155    {
156#   include "decl.inc"
157
158    /* first and last entry of tok.h cannot be grepped */
159      //case ATTRIB_CMD: strcpy(name,"ATTRIB_CMD"); break;
160    case MAX_TOK: strcpy(name,"MAX_TOK");       break;
161    default: strcpy(name,"(null)");
162  }
163#if 0
164  printf("[%d=%s]", n, name);
165  fflush(stdout);
166#endif
167  return(name);
168}
169
170#if 0
171static int iiTabIndex(const jjValCmdTab dArithTab, const int len, const int op)
172{
173  int a=0;
174  int e=len;
175  int p=len/2;
176  while ( a!=e)
177  {
178     if (op==dArithTab[p].cmd) return dArithTab[p].start;
179     else if (op<dArithTab[p].cmd)
180     { e=p; p=a+(e-a)/2;}
181     else
182     { a=p; p=p+(e-p)/2; }
183  }
184  return -1;
185}
186#endif
187
188/*========================================================================*/
189void PrintProc(
190  procdef pi
191  )
192{
193  int i;
194 
195  printf("proc: %s(", pi.procname);
196 
197  for(i=0; i<pi.paramcnt; i++) {
198    printf("%s", pi.param[i].name);
199    if(i < (pi.paramcnt-1)) printf(",");
200  }
201  printf(")\n");
202}
203
204/*========================================================================*/
205void make_version(char *p, moddefv module)
206{
207  char ver[10];
208  char date[16];
209  char libnamebuf[128];
210 
211  module->major = 0;
212  module->minor = 0;
213  module->level = 0;
214 
215  ver[0]='0'; ver[1]='.'; ver[2]='0'; ver[3]='.'; ver[4]='0'; ver[5]='\0';
216  date[0]='?'; date[1]='\0';
217  //if(what) sscanf(p,"%*[^=]= %*s %*s %10s %16s",ver,date);
218  sscanf(p,"%*s %*s %10s %16s",ver,date);
219  sscanf(ver, "%d.%d.%d", &module->major, &module->minor, &module->level);
220 
221  sprintf(libnamebuf,"(%s,%s)", ver, date);
222  if(strcmp(libnamebuf, "(0.0.0,?)")==0)
223  {
224    sscanf(p,"%*[^\"]\"%[^\"]\"",libnamebuf);
225  }
226  module->revision = (char *)malloc(strlen(libnamebuf)+1);
227  strcpy(module->revision, libnamebuf);
228}
229
230/*========================================================================*/
231void Add2files(
232  moddefv module,
233  char *name
234  )
235{
236  cfiles cfnew;
237  memset((void *)&cfnew, '\0', sizeof(cfiles));
238
239  cfnew.filename = (char *)malloc(strlen(name)+1);
240  memset(cfnew.filename, '\0', strlen(name)+1);
241  memcpy(cfnew.filename, name, strlen(name));
242
243  if(module->filecnt==0) {
244    module->files = (cfilesv)malloc(sizeof(cfiles)+1);
245  }
246  else {
247    module->files = (cfilesv)realloc(module->files,
248                                   (module->filecnt+1)*sizeof(cfiles));
249  }
250  if(module->files == NULL) { printf("ERROR\n"); return; }
251 
252  memset((void *) &module->files[module->filecnt], '\0', sizeof(cfiles));
253  memcpy((void *)(&(module->files[module->filecnt])),
254         (void *)&cfnew, sizeof(cfiles));
255  (module->filecnt)++;
256}
257
258/*========================================================================*/
259/*  procdefv Add2proclist(procdefv pi, char *name)*/
260void Add2proclist(
261  moddefv module,
262  char *name,
263  char *ret_val,
264  char *ret_typname,
265  int ret_typ
266  )
267{
268  procdef pnew;
269  logx("Add2proclist(%s, %s)\n", name, ret_val);
270 
271  memset((void *)&pnew, '\0', sizeof(procdef));
272  pnew.procname = (char *)malloc(strlen(name)+1);
273  if(pnew.procname==NULL) printf("Error 1\n");
274  pnew.funcname = (char *)malloc(strlen(name)+1);
275  memset(pnew.funcname, '\0', strlen(name)+1);
276  memset(pnew.procname, '\0', strlen(name)+1);
277  pnew.param = NULL;
278  (pnew).is_static = 0;
279  (pnew).paramcnt = 0;
280  strcpy(pnew.procname, name);
281  strcpy(pnew.funcname, name);
282
283  pnew.return_val.name = (char *)malloc(strlen(ret_val)+1);
284  memset(pnew.return_val.name, '\0', strlen(ret_val)+1);
285  memcpy(pnew.return_val.name, ret_val, strlen(ret_val));
286 
287  pnew.return_val.typname = (char *)malloc(strlen(ret_typname)+1);
288  memset(pnew.return_val.typname, '\0', strlen(ret_typname)+1);
289  memcpy(pnew.return_val.typname, ret_typname, strlen(ret_typname));
290  pnew.return_val.typ = ret_typ;
291 
292  if(module->proccnt==0) {
293    module->procs = (procdefv)malloc(sizeof(procdef)+1);
294  }
295  else {
296    module->procs = (procdefv)realloc(module->procs,
297                                   (module->proccnt+1)*sizeof(procdef));
298  }
299  if(module->procs == NULL) { printf("ERROR\n"); return; }
300 
301  memset((void *) &module->procs[module->proccnt], '\0', sizeof(procdef));
302  memcpy((void *)(&(module->procs[module->proccnt])),
303         (void *)&pnew, sizeof(procdef));
304  (module->proccnt)++;
305}
306
307/*========================================================================*/
308void AddParam(
309  moddefv module,
310  char *name,
311  char *typname,
312  int typ
313  )
314{
315  paramdef pnew;
316  int proccnt = module->proccnt-1;
317  int paramcnt = 0;
318
319  logx("AddParam(%d, %s, %s, %d)\n", module->procs[proccnt].paramcnt,
320       module->procs[proccnt].procname,
321       typname, typ);
322  memset((void *)&pnew, '\0', sizeof(paramdef));
323  pnew.name = (char *)malloc(strlen(name)+1);
324  memset(pnew.name, '\0', strlen(name)+1);
325  pnew.next = NULL;
326  memcpy(pnew.name, name, strlen(name));
327  pnew.typname = (char *)malloc(strlen(typname)+1);
328  memset(pnew.typname, '\0', strlen(typname)+1);
329  memcpy(pnew.typname, typname, strlen(typname));
330  pnew.typ = typ;
331
332  paramcnt = module->procs[proccnt].paramcnt;
333 if(module->procs[proccnt].paramcnt==0) {
334    module->procs[proccnt].param = (paramdefv)malloc(sizeof(paramdef));
335 }
336  else {
337    module->procs[proccnt].param =
338      (paramdefv)realloc(module->procs[proccnt].param,
339                         (paramcnt+1)*sizeof(paramdef));
340  }
341 
342  memcpy((void *)(&module->procs[proccnt].param[paramcnt]),
343         (void *)&pnew, sizeof(paramdef));
344  (module->procs[proccnt].paramcnt)++;
345  logx("AddParam() done\n");
346}
347
348/*========================================================================*/
349void PrintProclist(
350  moddefv module
351  )
352{
353  logx("PrintProclist()\n");
354  int j;
355  for(j=0; j<module->proccnt; j++) {
356    PrintProc(module->procs[j]);
357  }
358}
359
360/*========================================================================*/
361void generate_mod(
362  moddefv module
363  )
364{
365  procdefv v = NULL;
366  cfilesv c_filelist = NULL;
367  int proccnt;
368  FILE *fp_c, *fp_h;
369  char *filename;
370 
371  if(strcmp(S_UNAME, "ix86-Linux") == 0) {
372    systyp = SYSTYP_LINUX;
373  } else if (strcmp(S_UNAME, "HPUX-9")==0) {
374    systyp = SYSTYP_HPUX9;
375  } else if (strcmp(S_UNAME, "HPUX-10")==0) {
376    systyp = SYSTYP_HPUX10;
377  }
378  init_type_conv();
379  printf("SYSTYP:%d\n", systyp);
380 
381  filename = (char *)malloc(strlen(module->name)+5);
382  sprintf(filename, "%s.cc", module->name);
383  fp_c = fopen(filename, "w");
384  printf("Creating %s, ", filename);fflush(stdout);
385  mod_write_header(fp_c, module->name);
386  mod_write_enter_id(fp_c);
387
388  sprintf(filename, "%s.h", module->name);
389  fp_h = fopen(filename, "w");
390  write_header(fp_h, module->name);
391  printf("%s  ...", filename);fflush(stdout);
392 
393  /* building mod_init() */
394  fprintf(fp_c, "extern \"C\"\n");
395  fprintf(fp_c, "int mod_init(int(*iiAddCproc)())\n{\n");
396  fprintf(fp_c, "  idhdl h;\n\n");
397 
398  if(module->version != NULL) enter_id(fp_c, "version", module->version);
399  if(module->info != NULL) enter_id(fp_c, "info", module->info);
400  if(module->helpfile != NULL) enter_id(fp_c, "helpfile", module->helpfile);
401 
402  for(proccnt=0; proccnt<module->proccnt; proccnt++) {
403    printf("->%s, %s\n", module->procs[proccnt].procname,
404           module->procs[proccnt].funcname);
405    fprintf(fp_c, "  iiAddCproc(\"%s\",\"%s\",%s, mod_%s);\n",
406            module->name, module->procs[proccnt].procname, 
407            module->procs[proccnt].is_static ? "TRUE" : "FALSE",
408            module->procs[proccnt].funcname);
409  }
410  fprintf(fp_c, "  return 0;\n}\n\n");
411
412  /* building entry-functions */
413  for(proccnt=0; proccnt<module->proccnt; proccnt++) {
414    generate_function(&module->procs[proccnt], fp_c);
415    generate_header(&module->procs[proccnt], fp_h);
416  }
417  printf("  done.\n");fflush(stdout);
418  fclose(fp_c);
419  fclose(fp_h);
420}
421
422/*========================================================================*/
423void generate_header(procdefv pi, FILE *fp)
424{
425  int i;
426 
427  fprintf(fp, "BOOLEAN mod_%s(leftv res, leftv h);\n", pi->funcname);
428  switch( pi->return_val.typ) {
429      case SELF_CMD:
430        fprintf(fp, "BOOLEAN %s(res, ", pi->funcname);
431        break;
432
433      default:
434        fprintf(fp, "%s %s(", type_conv[pi->return_val.typ],
435                pi->funcname);
436  }
437  for (i=0;i<pi->paramcnt; i++) {
438    fprintf(fp, "%s res%d", type_conv[pi->param[i].typ], i);
439    if(i<pi->paramcnt-1) fprintf(fp, ", ");
440  }
441  fprintf(fp, ");\n\n");
442}
443
444void generate_function(procdefv pi, FILE *fp)
445{
446  int cnt = 0, i;
447  printf("%s has %d paramters\n", pi->funcname, pi->paramcnt);
448 
449  fprintf(fp, "BOOLEAN mod_%s(leftv res, leftv h)\n{\n", pi->funcname);
450  if(pi->paramcnt>0) {
451    if(pi->param[0].typ==SELF_CMD) {
452      fprintf(fp, "  return(%s(res,h));\n", pi->funcname);
453      fprintf(fp, "}\n\n");
454    }
455    else {
456      fprintf(fp, "  leftv v = h;\n");
457      fprintf(fp, "  int tok = NONE, index = 0;\n");
458      for (i=0;i<pi->paramcnt; i++)
459        fprintf(fp, "  leftv res%d = (leftv)Alloc0(sizeof(sleftv));\n", i);
460
461      fprintf(fp, "\n");
462   
463      for (i=0;i<pi->paramcnt; i++) {
464        fprintf(fp, "  if(v==NULL) goto mod_%s_error;\n", pi->funcname);
465        fprintf(fp, "  tok = v->Typ();\n");
466        fprintf(fp, "  printf(\"test %d.1\\n\");\n", i);
467        fprintf(fp, "  if((index=iiTestConvert(tok, %s))==0)\n",
468                pi->param[i].typname);
469        logx("==>'%s'\n", pi->param[i].typname);
470        fprintf(fp, "     goto mod_%s_error;\n", pi->funcname);
471        fprintf(fp, "  printf(\"test %d.2\\n\");\n", i);
472        fprintf(fp, "  if(iiConvert(tok, %s, index, v, res%d))\n",
473                pi->param[i].typname, cnt);
474        fprintf(fp, "     goto mod_%s_error;\n", pi->funcname);
475        fprintf(fp, "  printf(\"test %d.3\\n\");\n", i);
476        fprintf(fp, "  v = v->next;\n");
477      }
478      fprintf(fp, "  if(v!=NULL) { tok = v->Typ(); goto mod_%s_error; }\n",
479              pi->funcname);
480      fprintf(fp, "  printf(\"test before return\\n\");\n");
481
482      fprintf(fp, "\n");
483      switch( pi->return_val.typ) {
484          case SELF_CMD:
485            fprintf(fp, "    return(%s(res", pi->funcname);
486            for (i=0;i<pi->paramcnt; i++)
487              fprintf(fp, ", (%s) res%d->Data()",
488                      type_conv[pi->param[i].typ], i);
489            fprintf(fp, "));\n\n");
490           break;
491
492          default:
493            fprintf(fp, "  res->rtyp = %s;\n", pi->return_val.typname);
494            fprintf(fp, "  res->data = (void *)%s(", pi->funcname);
495            for (i=0;i<pi->paramcnt; i++) {
496              fprintf(fp, "(%s) res%d->Data()",
497                      type_conv[pi->param[i].typ], i);
498              if(i<pi->paramcnt-1) fprintf(fp, ", ");
499            }
500            fprintf(fp, ");\n  return FALSE;\n\n");
501      }
502     
503      fprintf(fp, "  mod_%s_error:\n", pi->funcname);
504      fprintf(fp, "    Werror(\"%s(`%%s`) is not supported\", Tok2Cmdname(tok));\n",
505              pi->procname);
506      fprintf(fp, "    Werror(\"expected %s(", pi->procname);
507      for (i=0;i<pi->paramcnt; i++) {
508        fprintf(fp, "'%s'", pi->param[i].name);
509        if(i!=pi->paramcnt-1) fprintf(fp, ",");
510      }
511      fprintf(fp, ")\");\n");
512      fprintf(fp, "    return TRUE;\n}\n\n");
513    }
514  } else {
515      fprintf(fp, "  return(%s(res));\n}\n\n", pi->funcname);
516  }
517     
518     
519}
520
521/*========================================================================*/
522void  mod_write_header(FILE *fp, char *module)
523{
524#if 0
525  FILE *fp;
526  char buf[BUFLEN];
527 
528  regex_t preg;
529  regmatch_t   pmatch[1];
530  size_t  nmatch = 0;
531  char *regex = "@MODULE_NAME@";
532
533  rc = regcomp(&preg, regex, REG_NOSUB);
534  if(rc) return -1;
535
536  if(!regexec(&preg, d_entry->d_name, nmatch, pmatch, REG_NOTBOL))
537    cert_count++;
538  regfree(&preg);
539 
540#else
541  write_header(fp, module);
542  fprintf(fp, "#include <stdlib.h>\n");
543  fprintf(fp, "#include <stdio.h>\n");
544  fprintf(fp, "#include <string.h>\n");
545  fprintf(fp, "#include <ctype.h>\n");
546  fprintf(fp, "%s\n", DYNAinclude[systyp]);
547  fprintf(fp, "\n");
548  fprintf(fp, "#include <locals.h>\n");
549  fprintf(fp, "#include \"%s.h\"\n", module);
550  fprintf(fp, "\n");
551#endif
552}
553
554/*========================================================================*/
555void write_header(FILE *fp, char *module, char *comment)
556{
557  fprintf(fp, "%s/*\n%s * This was automaticly generated by modgen\n",
558          comment, comment);
559  fprintf(fp, "%s * version %s\n", comment, MOD_GEN_VERSION);
560  fprintf(fp, "%s * module %s\n", comment, module);
561  fprintf(fp, "%s * Don't edit this file\n%s */\n", comment, comment);
562  fprintf(fp, "%s\n", comment);
563  fprintf(fp, "%s\n", comment);
564 
565}
566
567/*========================================================================*/
568void enter_id(FILE *fp, char *name, char *value)
569{
570  fprintf(fp, "  enter_id(\"%s\",\"%s\");\n",name, value);
571}
572
573void mod_write_enter_id(FILE *fp)
574{
575  fprintf(fp, "void enter_id(char *name, char *value)\n");
576  fprintf(fp, "{\n  idhdl h;\n\n");
577  fprintf(fp, "  h = enterid(mstrdup(name),0, STRING_CMD, &IDROOT, FALSE);\n");
578  fprintf(fp, "  if(h!=NULL) {\n");
579  fprintf(fp, "     IDSTRING(h) = mstrdup(value);\n");
580  fprintf(fp, "  }\n}\n\n");
581}
582
583static char *object_name(char *p)
584{
585  char *q = (char *)strrchr(p, '.');
586  if(q==NULL) return "";
587  *q = '\0';
588  char *r = (char *)malloc(strlen(p)+4);
589  switch(systyp) {
590      case SYSTYP_LINUX:
591        sprintf(r, "%s.lo", p);
592        break;
593       
594      case SYSTYP_HPUX9:
595        sprintf(r, "%s.o", p);
596        break;
597  }
598 
599  *q = '.';
600  return(r);
601}
602
603/*========================================================================*/
604void mod_create_makefile(moddefv module)
605{
606  FILE *fp;
607  fp = fopen("Makefile", "w");
608  cfilesv cf = module->files;
609  int i;
610 
611  printf("Creating Makefile  ...");fflush(stdout);
612  write_header(fp, module->name, "#");
613  fprintf(fp, "CC\t= gcc\n");
614  fprintf(fp, "CXX\t= gcc\n");
615  fprintf(fp, "CFLAGS\t= -DNDEBUG -I. -I../include\n");
616  fprintf(fp, "#LD\t=\n");
617  fprintf(fp, "\n");
618  fprintf(fp, "SRCS\t= ");
619 
620  for(i=0; i<module->filecnt; i++)
621    fprintf(fp, "%s ", cf[i].filename);
622
623  fprintf(fp, "\nOBJS\t= ");
624  for(i=0; i<module->filecnt; i++)
625    fprintf(fp, "%s ", object_name(cf[i].filename));
626
627  fprintf(fp, "\n\n");
628  switch(systyp) {
629      case SYSTYP_LINUX:
630        fprintf(fp, "all:\t%s.so\n", module->name);
631        fprintf(fp, "\n");
632        fprintf(fp, "%%.lo: %%.cc Makefile\n");
633        fprintf(fp, "\t${CC} ${CFLAGS} -c -fPIC -DPIC $< -o $*.lo\n");
634        fprintf(fp, "\n");
635 
636        fprintf(fp, "%%.la: %%.cc Makefile\n");
637        fprintf(fp, "\t${CC} ${CFLAGS} -c $< -o $*.la\n");
638        fprintf(fp, "\n");
639
640        fprintf(fp, "%s.so: ${OBJS}\n", module->name);
641        fprintf(fp, "\t${CC} ${CFLAGS} -shared -Wl,-soname -Wl,%s.so.%d \\\n",
642                module->name, module->major);
643        fprintf(fp, "\t\t-o %s.so.%d.%d.%d ${OBJS}\n", module->name,
644                module->major, module->minor, module->level);
645        fprintf(fp, "\trm -f %s.so\n", module->name);
646        fprintf(fp, "\tln -s %s.so.%d.%d.%d %s.so\n", module->name, module->major,
647                module->minor, module->level, module->name);
648        fprintf(fp, "\n");
649        break;
650
651      case SYSTYP_HPUX9:
652        fprintf(fp, "all:\t%s.sl\n", module->name);
653        fprintf(fp, "\n");
654        fprintf(fp, "%%.o: %%.cc Makefile\n");
655        fprintf(fp, "\t${CC} ${CFLAGS} -c -fPIC -DPIC $< -o $*.o\n");
656        fprintf(fp, "\n");
657        fprintf(fp, "%s.sl: ${OBJS}\n", module->name);
658        fprintf(fp, "\t${LD} -b -o %s.sl \\\n", module->name);
659        fprintf(fp, "\t\t${OBJS}\n");
660        break;
661       
662  }
663
664  fprintf(fp, "clean:\n");
665  fprintf(fp, "\trm -f *.o *.lo *.so* *.sl *.la *~ core\n\n");
666 
667  fprintf(fp, "distclean: clean\n");
668  fprintf(fp, "\trm -f %s.cc %s.h Makefile\n\n", module->name, module->name);
669 
670  fprintf(fp, "\n");
671  fprintf(fp, "\n");
672
673  fclose(fp);
674  printf("  done.\n");
675}
676
677/*========================================================================*/
Note: See TracBrowser for help on using the repository browser.