source: trunk/etc/src/Ydf1.cc @ 503

Last change on this file since 503 was 503, checked in by lnalod, 13 years ago

CeCILL license.

File size: 47.0 KB
Line 
1/*
2Copyright or © or Copr. Charles SORROR (2011/01/13)
3
4mail of the author: cslod@locean-ipsl.upmc.fr
5
6This software is a framework for variational data assimilation in
7numerical models.
8
9This software is governed by the CeCILL license under French law and
10abiding by the rules of distribution of free software.  You can  use,
11modify and/ or redistribute the software under the terms of the CeCILL
12license as circulated by CEA, CNRS and INRIA at the following URL
13"http://www.cecill.info".
14
15As a counterpart to the access to the source code and  rights to copy,
16modify and redistribute granted by the license, users are provided only
17with a limited warranty  and the software's author,  the holder of the
18economic rights,  and the successive licensors  have only  limited
19liability.
20
21In this respect, the user's attention is drawn to the risks associated
22with loading,  using,  modifying and/or developing or reproducing the
23software by the user in light of its specific status of free software,
24that may mean  that it is complicated to manipulate,  and  that  also
25therefore means  that it is reserved for developers  and  experienced
26professionals having in-depth computer knowledge. Users are therefore
27encouraged to load and test the software's suitability as regards their
28requirements in conditions enabling the security of their systems and/or
29data to be ensured and,  more generally, to use and operate it in the
30same conditions as regards security.
31
32The fact that you are presently reading this means that you have had
33knowledge of the CeCILL license and that you accept its terms.
34*/
35
36//g++ Ydf1.cc -Wall -o Ydf1
37
38#include <stdio.h>
39#include <string.h>
40#include <stdlib.h>
41#include <ctype.h>
42
43#define BUFSIZE           2048
44#define LG_MAX_NAME         24
45#define NB_MAX_VARIAB    10000
46#define LG_MAX_BIGVAR      128
47#define NB_MAX_EXPRESYM  10000
48#define NB_MAX_DIFFVAR   10000
49//#define NB_MAX_CPLX     1000
50
51/*=============================================================================*/
52struct st_diff {
53        char            vardiff[LG_MAX_NAME*2 + 1];
54        int             deblockportee;
55};
56
57/*=============================================================================*/
58short   trace=0;
59FILE    *fpmodul, *fpginac;
60//char    modul_file_name[LG_MAX_NAME+1];
61int     i, j=0, k;
62char      buffer[BUFSIZE+1];
63char    delim[] =" \t(),\n";
64//char    *pstr1, *pstr3, *pstrw;
65//char    *pstr2=NULL;
66short   Phase=0;
67int     NbIn, NbOut;
68int     indicYS=0;
69int     indic=0;
70char      instruct[BUFSIZE+1];
71short   indicBLOCK=0;
72short   indicCROUV=0;
73short   indicTAB=0;
74char    TabVar[NB_MAX_VARIAB][LG_MAX_BIGVAR+1];
75int     NbVar=0;
76short   indicDECLAR=0;
77short   indicAFFECT=0;
78short   prodlevel=0;
79char    Ysubstit[LG_MAX_NAME+1];
80int     iexp;
81
82char    TabExpreSym[NB_MAX_EXPRESYM][LG_MAX_NAME + 1];
83short   TabFlagIn[NB_MAX_EXPRESYM];
84int     NbExpreSym = 0;
85//char    affectsv[BUFSIZE+1];
86struct  st_diff TabDiff[NB_MAX_DIFFVAR];
87int     NbDiff = 0;
88
89int     CurBlockLev = 0; //semaphore de decompte des accolades pour gerer le niveau d'imbrication des block
90
91char    ModulName[LG_MAX_NAME+1];
92//int     lenModulName;
93
94char    TabDejaDiff[NB_MAX_DIFFVAR][LG_MAX_NAME+1]; //!!! tableau en global a usage local : initialement, et
95int     NbDejaDiff;                                 //    localement, mettre NbDejaDiff a ZERO !
96
97short   flagCPLX=0;
98int     NbInCplx=0;
99//char    TabCplx[NB_MAX_CPLX][LG_MAX_NAME + 1];
100//int     NbCplx=0;
101
102//principaux mots du langage C/C++ (liste non exhaustive ... )
103#define NB_CWORD  109
104char    TabCword [NB_CWORD][LG_MAX_NAME] =
105{       "abs",      "acos",     "asin",     "atan",    "atan2",    "atoi",
106        "atof",     "atol",     "break",    "case",    "char",     "close",  "complex",
107        "const",    "continue", "cos",      "cosh",    "default",  "delete",
108        "div",      "do",       "double",   "enum",    "else",     "exp",
109        "exit",     "extern",   "fabs",     "float",   "fclose"    "feof",
110        "fgetc",    "fgets",    "fopen",    "for",     "fprintf",  "fputc",
111        "fputs",    "free",     "getc",     "getchar", "getenv",   "gets",
112        "goto",     "if",       "int",      "isalnum", "isdigit",  "islower",
113        "isupper",  "log",      "log10",    "long",    "memchr",   "memcmp",
114        "memcpy",   "memove",   "new",      "NULL",    "open",     "pow",
115        "putenv",   "puts",     "rand",     "read",    "return",   "scanf",
116        "setenv",   "sprintf",  "short",    "sin",     "sinh",     "sizeof",
117        "sqrt",     "srand",    "sscanf",   "static",  "stdin",    "stdout",
118        "strcat",   "strchr",   "strcmp",   "strcpy",  "strlen",   "strncat",
119        "strncmp",  "strncpy",  "strpbrk",  "strrchr", "strspn",   "strstr",
120        "strtok",   "strtol",   "struct",   "switch",  "tan",      "tanh",
121        "tolower",  "toupper",  "typedef",  "union",   "unsigned", "void",
122        "volatile", "vfprintf", "vsprintf", "while",   "write",    "YREAL",
123};
124
125/*=============================================================================*/
126
127//*---------------------------------------------------------------------------*/
128int c_word(char *word)
129{   int wi;
130    for (wi=0; wi<NB_CWORD; ++wi)
131    {     if (!strcmp(word, TabCword[wi]))
132                 return (1);
133    }
134    return(0);
135}
136//*---------------------------------------------------------------------------*/
137char *str_affect(char *str)
138{    char *pstr;
139
140     pstr = strstr(str, "+=");  if (pstr != NULL) return pstr;
141     pstr = strstr(str, "-=");  if (pstr != NULL) return pstr;
142     pstr = strstr(str, "*=");  if (pstr != NULL) return pstr;
143     pstr = strstr(str, "/=");  if (pstr != NULL) return pstr;
144
145     pstr = strstr(str, "==");
146     if (pstr != NULL)  return (str_affect(pstr+2));
147     pstr = strstr(str, ">=");
148     if (pstr != NULL)  return (str_affect(pstr+2));
149     pstr = strstr(str, "<=");
150     if (pstr != NULL)  return (str_affect(pstr+2));
151     pstr = strstr(str, "!=");
152     if (pstr != NULL)  return (str_affect(pstr+2));
153     //autres cas non traited plm : <<=, >>=, &=, ^=, |=
154
155     //et enfin le cas d'une simple affectation
156     pstr = strstr(str, "=");  if (pstr != NULL) return pstr;
157
158     return(NULL);
159}
160/*---------------------------------------------------------------------------*/
161void str_lesschr(char *str, char car)
162{ int lg, i,j;
163  lg = strlen(str);
164  i=j=0;
165  for (i=0; i<lg; ++i)
166  {   if (str[i]==car) continue;
167      str[j]=str[i];
168      ++j;
169  }
170  str[j]='\0';
171}
172/*---------------------------------------------------------------------------*/
173int str_qalphanum(char *str)
174{   int lgstr = strlen(str);
175    int i=0;
176    short alphok=0;
177    while (i<lgstr)
178    {  if ( !isalnum(str[i]) && str[i]!='_') return(0);
179       if ( isalpha(str[i]) || str[i]=='_') alphok = 1;
180       ++i;
181    }
182    if (alphok) return(1);
183    return(0);
184}
185/*---------------------------------------------------------------------------*/
186int str_qdigit(char *str)
187{   int lgstr = strlen(str);
188    int i;
189    for (i=0; i<lgstr; ++i)
190    {  if (!isdigit(str[i])) return(0);
191    }
192    return(1);
193}
194/*---------------------------------------------------------------------------*/
195char *str_tok(char *str, char *delim, char *svdelim, char *pmax)
196{    char *p1, *p2;
197
198     if (str>=pmax) return (NULL);
199
200     p1 = str;
201     //se positionner sur le 1er caratere non delimiteur
202     while (p1[0]!='\0' && strchr(delim, p1[0])!=NULL) ++p1;
203     //avancer tant qu'on ne retombe pas sur un caratere delimiteur
204     p2=p1;
205     while (p2[0]!='\0' && strchr(delim, p2[0])==NULL) ++p2;
206     //on informe du delimiteur trouved avant de l'ecraser par '\0'
207     *svdelim=p2[0];
208     p2[0]='\0';
209     return(p1);
210}
211
212/*---------------------------------------------------------------------------*/
213void BackwardOut(char *instruct)
214{    char   *pstr1, *pstr2;
215     char    bufwrk[BUFSIZE+1];
216
217     if (trace) printf("\n/*BO:%s:*/\n", instruct);
218
219     strcpy(bufwrk, instruct);
220     pstr1 = bufwrk;
221                 fprintf(fpginac, "  cout ");
222     while (1)
223     {  pstr2 = strpbrk(pstr1, "\n\"");
224        if (pstr2!=NULL)
225        {
226           if (pstr2[0]=='\n')
227           {  pstr2[0]='\0';
228              fprintf(fpginac," <<\"%s\" <<endl ",pstr1);
229              pstr1=pstr2+1;
230           }
231           else
232           {  pstr2[0]='\0';
233              fprintf(fpginac,"<<\"%s\\\"\" ", pstr1);
234              pstr1=pstr2+1;
235           }
236        }
237        else
238        { fprintf(fpginac," <<\"%s\"",pstr1);
239          break;
240        }
241     }
242     fprintf(fpginac, " ;\n");
243}
244
245/*---------------------------------------------------------------------------*/
246int add_var(char *strvar)
247{
248    if (NbVar>=NB_MAX_VARIAB)
249    {  printf("Ydf1: too much variables in that modul (%s)\n", ModulName);
250       exit(-9);
251    }
252    strcpy(TabVar[NbVar], strvar);
253    ++NbVar;
254    return(NbVar-1);
255}
256
257/*---------------------------------------------------------------------------*/
258short is_yadvar(char *str)
259{   char bufstr[7];
260    strncpy(bufstr, str, 6);  //strcpy(bufstr, str);
261    bufstr[6]='\0';
262    return (!strcmp(bufstr, "Yadvar"));
263}
264
265/*---------------------------------------------------------------------------*/
266int exist_expresym(char *expresym)
267{
268    int wi;
269    for (wi=0; wi<NbExpreSym; ++wi)
270    {   if (!strcmp(expresym, TabExpreSym[wi]))
271           return (1);
272    }
273    return(0);
274}
275
276/*---------------------------------------------------------------------------*/
277int id_diff(char *diff)
278{
279    int wi;
280    for (wi=0; wi<NbDiff; ++wi)
281    {   if (!strcmp(diff, TabDiff[wi].vardiff))
282               return (wi);
283    }
284    return(-1);
285}
286/*---------------------------------------------------------------------------*/
287void decrem_diff_blocklev()
288{
289    int wi;
290    for (wi=0; wi<NbDiff; ++wi)
291    {     if (TabDiff[wi].deblockportee  == CurBlockLev)
292           TabDiff[wi].deblockportee = 0;
293    }
294    --CurBlockLev;
295}
296
297/*---------------------------------------------------------------------------*/
298/*int is_input(char *str)
299{
300    int wi;
301    for (wi=0; wi<NbIn; ++wi)
302    {     if (!strcmp(str, TabExpreSym[wi]))
303                 return (1);
304    }
305    return(0);
306}
307int is_input(char *str)
308{
309    int wi, nballin;
310                nballin = NbIn+NbInCplx;
311    for (wi=0; wi<nballin; ++wi)
312    {     if (!strcmp(str, TabExpreSym[wi]))
313                 return (1);
314    }
315    return(0);
316}
317*/
318int id_input(char *input)
319{
320    int wi, nballin;
321                nballin = NbIn+NbInCplx;
322    for (wi=0; wi<nballin; ++wi)
323    {   if (!strcmp(input, TabExpreSym[wi]))
324               return (wi);
325    }
326    return(-1);
327}
328
329/*---------------------------------------------------------------------------*/
330int id_YSi(char *tok)
331{   int num;
332    if (tok[0]!='Y' || tok[1]!='S') return(0);
333                if (tok[2]=='0') return(0);
334                if (!str_qdigit(&tok[2])) return (0);
335                num = atoi(&tok[2]);
336                if (num<=NbOut) return(num);
337    return(0);
338}
339
340/*---------------------------------------------------------------------------*/
341void transfo_affect(char *instruct, char *pstr2)
342{//   ...VAR {+,-,*,/}= EXPR ;   a tranformer en :--->    VAR = VAR {+,-,*,/} ( EXPR ) ;
343 //   ( avec pstr2 qui pointera sur le = et non plus le {+,-,*,/}= )
344
345     char    bufwrk[BUFSIZE+1];
346     char    *p3;
347
348     //printf("befor|%s|%c|\n", instruct, pstr2[0]);
349
350                 memset(bufwrk, '\0', BUFSIZE+1);
351                 bufwrk[0]=pstr2[-1];
352                 pstr2[-1] = '\0'; //on termine la variable affectee par un '\0'
353
354                 //il faut retrouver la variable affectee (ie se positionner dessus)
355                 p3 = pstr2-2;
356     while ((p3[0]==' ' || p3[0]=='\t') && p3>instruct) --p3; //on remonte les espaces et \t
357     while (p3[0]!=' ' && p3[0]!='\t' && p3>instruct) --p3; //on remonte les autres caractères
358                 if (p3<instruct) p3=instruct; //en faisant attention de rester sur l'instruction
359
360                 //
361                 strcat(bufwrk, "= ");                                                                  //'= '
362                 strcat(bufwrk, p3);                                                                            //VAR
363                 strcat(bufwrk, " ");                                                                           //' '
364                 bufwrk[strlen(bufwrk)] = pstr2[0];               //{'+','-','*','/'}
365                 strcat(bufwrk, " (");                                                                  //' ('
366                 strcat(bufwrk, pstr2+2);                                                               //EXPR ;
367                 bufwrk[strlen(bufwrk)-1] = '\0';               //pour enlever le ';' de fin
368                 strcat(bufwrk, " ) ;");                                                                //et le remplacer par ' ) ;"
369
370                 //
371                 strcat(instruct, bufwrk);
372
373     //printf("after|%s|%c|\n", instruct, pstr2[0]);
374}
375
376/*---------------------------------------------------------------------------*/
377void substitut_by_symbol(char *str)
378{    char    *pstr1, *pmax;
379     char    bufwrk[BUFSIZE+1];
380     char    delim;
381     char    *p1;
382     strcpy(bufwrk, str);
383     memset(str, '\0', strlen(str)); //raz de la string qu'on va
384     //reconstruire en substituant les QAN par leur equivalent symbol
385     pstr1 = bufwrk;
386     pmax = pstr1+strlen(pstr1);
387     while ((p1=str_tok(pstr1, " \n\t", &delim, pmax))!=NULL)
388     {
389               if (str_qalphanum (p1))
390            if (!c_word(p1) && !is_yadvar(p1))
391               if (exist_expresym(p1))
392         {
393                  strcat(str, "Ygs_");
394         }
395         strcat(str, p1);
396         sprintf(str, "%s%c", str, delim);
397               pstr1 = pstr1+strlen(pstr1)+1;
398     }
399}
400
401/*---------------------------------------------------------------------------*/
402void substitut_produce_tab(char *instruct)
403{    //on a detected qu'il y avait 1 (ou plusieurs) tableau dans instruct
404     //on va les substituer, ..., mais avant, il faut les trouver ...
405     char   *pstr1, *pstr2, *pstr3;
406     char    bufwrk[BUFSIZE+1];
407     char    strtab[LG_MAX_BIGVAR+1];
408     int     idvar;
409     int     semcro;
410     char    yadvari[LG_MAX_NAME+1];
411                 //printf("TAB(S) FOUND IN |%s|\n", instruct);
412
413     strcpy(bufwrk, instruct);
414     memset(instruct, '\0', strlen(instruct)); //raz d'instruct qu'on va
415     //reconstruire en substituant les tableaux s'il y en a (risqued!?)
416
417     fprintf(fpginac,"  cout<<endl;\n");
418
419     pstr1 = bufwrk;
420     while (1)
421     {
422        pstr2 = strchr(pstr1, '[');
423        semcro=1;
424        if (pstr2!=NULL)
425        {  //pstr2 pointe sur le debut de tableau, il faut en trouver la fin
426           pstr3=pstr2+1;
427           while (1)
428           {   pstr3=strpbrk(pstr3, "][");
429               if (pstr3!=NULL)
430               {
431                              if (pstr3[0]=='[') ++semcro; else --semcro; //
432                              ++pstr3;
433                  if (pstr3[0]!='['  && semcro==0) break;
434               }
435               else break; //?
436           }
437           //rendu ici, pstr3 est sensed pointer sur l'octet qui suit le
438           //crochet de fin du tableau
439
440           //maintenant, on remonte pstr2 en arriere pour se mettre au debut
441           //de la variable tableau
442           while (pstr2[0]!=' ' && pstr2[0]!='\t' && pstr2[0]!='\n') --pstr2;
443
444           //on met des /0 pour delimiter et creer la string tableau
445           pstr2[0]='\0'; ++pstr2; //debut de la string tableau
446           pstr3[0]='\0';          //fin de la string tableau
447                                         //printf ("->|%s|%s|%s|<-\n", pstr1, pstr2, pstr3+1); //pour verif du decoupage
448
449                 strcpy(strtab, pstr2);
450           str_lesschr(strtab, ' ');
451                                         //printf ("->|%s|<-\n", strtab);
452
453           //ajout de ce tableau comme variable dans un tableaux de variable
454           idvar = add_var(strtab);
455           sprintf (yadvari, "Yadvar%i", idvar); //
456           //creation du symbol pour le tableau
457           fprintf(fpginac,"  symbol %s(\"%s\");\n", yadvari, yadvari);
458
459           //declaration de la variable intermediaire pour backward
460           fprintf(fpginac,"  cout<<\"double %s = %s;\"<<endl;\n", yadvari, strtab);
461
462           //substitution : on reconstruit instruct (qu'on a razeder au debut)
463           strcat(instruct, pstr1);
464           strcat(instruct, " ");
465           strcat(instruct, yadvari);
466
467           //on repositionne pstr1 pour la suite, y'a peut etre encore d'autres tableaux?
468           pstr1 = pstr3+1;
469        }
470        else
471        {  strcat(instruct, pstr1);   //fin de reconstruction de instruct
472           break;
473        }
474     }
475}
476
477/*---------------------------------------------------------------------------*/
478void BackProduce_DAdx(char *instruct)
479{    char   *pstr, *pmax;
480     char   bufwrk[BUFSIZE+1];
481     char   delim;
482     char   *p1;
483     char   DA_dx[LG_MAX_NAME*2+1];
484     int    wi, idiff;
485int nballin, startin;
486nballin = NbIn+NbInCplx;
487if (flagCPLX) startin=NbIn; else startin=0;
488
489     strcpy(bufwrk, instruct);
490     pstr = bufwrk;
491     pmax = pstr+strlen(pstr);
492     while ((p1=str_tok(pstr, " \n\t", &delim, pmax))!=NULL)
493     {
494               if (str_qalphanum(p1))
495            if (!c_word(p1) && !is_yadvar(p1))
496                                 {
497//            for (wi=0; wi<NbIn; ++wi)
498for (wi=startin; wi<nballin; ++wi)
499            {
500                sprintf(DA_dx, "YD%s_d%s", p1, TabExpreSym[wi]);
501                      idiff = id_diff(DA_dx);
502                      if (idiff<0) //ce qui veut dire qu'on rencontre DA_dx pour la 1ere fois
503                {
504                   if (NbDiff>=NB_MAX_DIFFVAR)
505                   {  printf(" Ydf1: Automatic derivativ stopped for modul %s\n", ModulName);
506                      printf("       because :=> too much derivative in that modul\n");
507                      exit(-9);
508                   }
509                               strcpy(TabDiff[NbDiff].vardiff, DA_dx);
510                               TabDiff[NbDiff].deblockportee = CurBlockLev;
511                   ++NbDiff;
512                   fprintf(fpginac,"  cout<<\"double %s; \"<<endl;\n", DA_dx);
513                }
514                else //DA_dx existe deja, mais pour backward il faut eventuellement
515                {    //produire de nouveau la declaration en tenant compte de l'imbrication des blocks !
516                   if (TabDiff[idiff].deblockportee == 0)
517                   {  TabDiff[idiff].deblockportee = CurBlockLev;
518                                  fprintf(fpginac,"  cout<<\"double %s; \"<<endl;\n", DA_dx);
519                   }
520                }
521            }
522                                 }
523         pstr = pstr+strlen(pstr)+1;
524     }
525}
526
527/*---------------------------------------------------------------------------*/
528void Sto_GinProduce_ExpreSym(char *str)
529{    char    *pstr, *pmax;
530     char    bufwrk[BUFSIZE+1];
531     char    delim;
532     char    *p1;
533     strcpy(bufwrk, str);
534     pstr = bufwrk;
535     pmax = pstr+strlen(pstr);
536/*
537short  vuegal=0;
538printf("SGPESI: |%s|\n", instruct);
539*/
540     while ((p1=str_tok(pstr, " \n\t", &delim, pmax))!=NULL)
541     {
542/*
543if (p1[0]=='=') vuegal=1;
544*/
545               if (str_qalphanum(p1))
546            if (!c_word(p1) && !is_yadvar(p1))
547               if (!exist_expresym(p1))
548               {
549                  if (NbExpreSym>=NB_MAX_EXPRESYM)
550                  {  printf(" Ydf1: Automatic derivativ stopped for modul %s\n", ModulName);
551                     printf("       because :=> too much token in that modul\n");
552                     exit(-9);
553                  }
554/*nb: on est dans cette fct que si queaffect,
555CELA N'EST SANS DOUTE PLUS VRAI
556donc la variable n'a pas du faire l'objet
557//    d'une declaration ce qui laisse penser qu'il s'agit d'une variable externe.
558//    Si on est sur le token qui precede le '=', alors cela voudrait dire qu'on est en
559//    train de de modifier cette variable externe, ce qui du coup modifie la fonction
560//    elle meme, ce qui not fair et rend les testdf KO, --> WARNING
561if (!vuegal)
562{  printf("WARNING: you may be are modifying a extenal variable (%s) ...\n", p1);
563   printf("         this is not fair and may make failed the validation functions test\n");
564}
565*/
566                  strcpy(TabExpreSym[NbExpreSym], p1);
567                  ++NbExpreSym;
568                              fprintf(fpginac,"  ex %s;\n", p1);
569                              fprintf(fpginac,"  symbol Ygs_%s(\"Ygs_%s\");\n", p1, p1);
570               }
571               pstr = pstr+strlen(pstr)+1;
572     }
573}
574
575/*---------------------------------------------------------------------------*/
576short dejadiff(char *var2diff)
577{   //char   TabDejaDiff[NB_MAX_DIFFVAR][LG_MAX_NAME+1];
578    //!!! tableau en global a usage local : initialement, et
579                //    localement, mettre NbDejaDiff a ZERO !
580    int wi;
581    for (wi=0; wi<NbDejaDiff; ++wi)
582    {   if (!strcmp(var2diff, TabDejaDiff[wi]))
583               return (1);
584    }
585    return(0);
586}
587
588/*---------------------------------------------------------------------------*/
589void GinBackProduce_dfDf(char *A, char *straffect) //A = straffect
590{                //maintenant, il faut produire les derivees.
591     //1) il faut  produire dans ginac les derivee de tous les QAN de droite pour celui de gauche :
592     //   ex avec : A = f(sB, sB, sC, ...)
593     //   on doit obtenir : da_DB = A.diff(sB,1);  UNE SEULE FOIS
594     //                                                                                 da_DC = A.diff(sC,1);    ...
595     //algo:
596     // pour chaque variable (V) de straffect (en considerant qu'un token QAN !c_word et !yadvare est une variable (quid des constantes?)
597     // construire da_DV
598     // si dA_DV n'existe pas dans Tabdiff alors l'y ajouter et creer "ex da_DV;" pour ginac
599     // produire pour ginac : "da_DV = A.diff(Ygs_V, 1);" une seule fois pour chaque variable
600     char   *pstr, *pmax;
601     char    bufwrk[BUFSIZE+1];
602     char    delim;
603     char    dA_DV[LG_MAX_NAME*2+1];
604     int     idiff;
605     char    *p1;
606
607                 NbDejaDiff=0; //usage du tableau TabDejaDiff pour s'assurer qu'on ne derive qu'une seule fois une variable
608                               //et meme si, lorsqu'en particulier elle apparait plusieurs fois en partie droite
609
610     strcpy(bufwrk, straffect);
611                 pstr = bufwrk;
612     pmax = pstr+strlen(pstr);
613     while ((p1=str_tok(pstr, " \n\t", &delim, pmax))!=NULL)
614     {
615               if (str_qalphanum(p1))
616            if (!c_word(p1) && !is_yadvar(p1))
617         {
618               sprintf(dA_DV, "Yd%s_D%s", A, p1);
619                     idiff = id_diff(dA_DV);
620                     if (idiff<0) //ce qui veut dire qu'on rencontre dA_DV pour la 1ere fois
621               {
622                  if (NbDiff>=NB_MAX_DIFFVAR)
623                  {  printf(" Ydf1: Automatic derivativ stopped for modul %s\n", ModulName);
624                     printf("       because :=> too much derivative in that modul\n");
625                     exit(-9);
626                  }
627                              strcpy(TabDiff[NbDiff].vardiff, dA_DV);
628                              TabDiff[NbDiff].deblockportee = CurBlockLev;
629                  ++NbDiff;
630                              fprintf(fpginac,"  ex %s;\n", dA_DV);
631                  fprintf(fpginac,"  cout<<\"double %s; \"<<endl;\n", dA_DV);
632               }
633               else //dA_DV existe deja, mais pour backward il faut eventuellement
634               {    //produire de nouveau la declaration en tenant compte de l'imbrication des blocks !
635                  if (TabDiff[idiff].deblockportee == 0)
636                  {  TabDiff[idiff].deblockportee = CurBlockLev;
637                                 fprintf(fpginac,"  cout<<\"double %s; \"<<endl;\n", dA_DV);
638                  }
639               }
640
641                                                         //pour ne produire la derivee qu'une seule fois
642                                                         if (!dejadiff(dA_DV))
643               {  if (NbDejaDiff>=NB_MAX_DIFFVAR)
644                  {  printf(" Ydf1: Automatic derivativ stopped for modul %s\n", ModulName);
645                     printf("       because :=> too much derivative in that modul\n");
646                     exit(-9);
647                  }
648                                                                  strcpy(TabDejaDiff[NbDejaDiff], dA_DV);
649                                                                        ++NbDejaDiff;
650                                                            fprintf(fpginac,"  %s = %s.diff(Ygs_%s, 1);\n", dA_DV, A, p1);
651                  fprintf(fpginac,"  cout<<\"%s = \" <<csrc<< %s <<\";\"<<endl;\n", dA_DV, dA_DV);
652               }
653         }
654               pstr = pstr+strlen(pstr)+1;
655     }
656}
657
658/*---------------------------------------------------------------------------*/
659void BackProduce_Dfdx(char *A, char *straffect)
660{    //2) puis il faut produire la derivee du terme de gauche par rapport aux entrees.
661     //   il s'agit de faire, directement dans le backward, la somme pour chaque entree xi :
662     //             DA_dxi = dA_DV1.DV1_dxi + ... + dA_DVn.DVn_dxi
663     char   *pstr, *pmax;
664     char    bufwrk[BUFSIZE+1];
665     char    delim;
666     char    DA_dx[LG_MAX_NAME*2+1];
667     int     wi;
668     char    dA_DV[LG_MAX_NAME*2+1];
669     int     idiff;
670     char    *p1;
671     char    DV_dx[LG_MAX_NAME*2+1];
672int nballin, startin;
673nballin = NbIn+NbInCplx;
674if (flagCPLX) startin=NbIn; else startin=0;
675     //pmax = straffect+strlen(straffect);
676//---
677//     for (wi=0; wi<NbIn; ++wi)
678//for (wi=startin; wi<nballin; ++wi)
679for (wi=0; wi<nballin; ++wi)
680     {
681if (TabFlagIn[wi]==-1) continue; //entree reelle comprise dans une entree complexe
682
683         if (indicYS<=0) //(!isYSi)
684         {
685            sprintf(DA_dx, "YD%s_d%s", A, TabExpreSym[wi]);
686                  idiff = id_diff(DA_dx);
687                  if (idiff<0) //ce qui veut dire qu'on rencontre DA_dx pour la 1ere fois
688            {
689               if (NbDiff>=NB_MAX_DIFFVAR)
690               {  printf(" Ydf1: Automatic derivativ stopped for modul %s\n", ModulName);
691                  printf("       because :=> too much derivative in that modul\n");
692                  exit(-9);
693               }
694                           strcpy(TabDiff[NbDiff].vardiff, DA_dx);
695                           TabDiff[NbDiff].deblockportee = CurBlockLev;
696               ++NbDiff;
697               fprintf(fpginac,"  cout<<\"double %s; \"<<endl;\n", DA_dx); //+pB
698            }
699            else //DA_dx existe deja, mais pour backward il faut eventuellement
700            {    //produire de nouveau la declaration en tenant compte de l'imbrication des blocks !
701               if (TabDiff[idiff].deblockportee == 0)
702               {  TabDiff[idiff].deblockportee = CurBlockLev;
703                              fprintf(fpginac,"  cout<<\"double %s; \"<<endl;\n", DA_dx);
704               }
705            }
706         }
707         else
708            sprintf(DA_dx, "YJ%iI%i", indicYS, wi+1);
709//---
710         fprintf(fpginac,"  cout<<\"%s = \";", DA_dx);
711
712                                 NbDejaDiff=0;
713
714             strcpy(bufwrk, straffect);
715         pmax = bufwrk+strlen(bufwrk);
716         pstr = bufwrk;
717               while ((p1=str_tok(pstr, " \n\t", &delim, pmax))!=NULL)
718           {
719                   if (str_qalphanum(p1))
720                 if (!c_word(p1) && !is_yadvar(p1))
721             {
722                                                                  sprintf(dA_DV, "Yd%s_D%s", A, p1);
723                                                                  sprintf(DV_dx, "YD%s_d%s", p1, TabExpreSym[wi]); //.
724
725                                                            //pour ne produire la derivee qu'une seule fois
726                                                                        if (!dejadiff(dA_DV))
727                                                                        {  if (NbDejaDiff>=NB_MAX_DIFFVAR)
728                                                                                 {  printf(" Ydf1: Automatic derivativ stopped for modul %s\n", ModulName);
729                                                                                          printf("       because :=> too much derivative in that modul\n");
730                                                                                                 exit(-9);
731                                                                                        }
732                                                                                        strcpy(TabDejaDiff[NbDejaDiff], dA_DV);
733                                                                                        ++NbDejaDiff;
734                      if (!strcmp(p1, TabExpreSym[wi]))
735                      {  //fprintf(fpginac,"  cout<<\"Yd%s_D%s + \";", A, p1);
736                                                                               fprintf(fpginac,"  cout<<\"%s + \";", dA_DV);
737                      }
738                      else if (id_input(p1)==-1) //(!is_input(p1))
739                      {  //fprintf(fpginac,"  cout<<\"Yd%s_D%s*YD%s_d%s + \";", A, p1, p1, TabExpreSym[wi]);
740                         if (id_diff(DV_dx)>=0) //on s'assure que DV_dx existe bien ...
741                                                                                            fprintf(fpginac,"  cout<<\"%s*%s + \";", dA_DV, DV_dx);
742                      }
743                                                                        }
744             }
745                   pstr = pstr+strlen(pstr)+1;
746         }
747               fprintf(fpginac,"  cout <<\"0;\"<<endl;\n");
748     }
749}
750
751/*----------------------------------------------------------------------------*/
752/*============================================================================*/
753void quedeclar (char *instruct, char *pstr2)
754{  if (trace) printf("\n/*indicDECLAR & !indicAFFECT:|%s|%s|*/\n", instruct, pstr2);
755   //un token de Type (double, float, ...) a ete rencontred et pstr2 pointe dessus
756   //exemple soil_CG:         "} else { double ZFROZEN2;"
757   //on va decouper l'instruction en 2 morceaux : Debut (instruct), et la declaration proprement dite (pstr2)
758   pstr2[-1]='\0'; //nb: le token est en principe preceded d'au moins un ' ' ou '\t'
759   //on produit le debut
760   if (instruct<pstr2)
761      BackwardOut(instruct); //d'abord le debut de l'instruction
762
763   //on produit DAdx pour backward
764   BackProduce_DAdx(pstr2);
765         //on stocke et produit pour ginac les QAN d'instruct dans TabExp si ils n'existe pas deja (ni en symbol)
766   Sto_GinProduce_ExpreSym(pstr2);
767
768   //on reconduit la suite (declaration proprement dite) tel quel pour backward
769   BackwardOut(pstr2);
770}
771
772/*---------------------------------------------------------------------------*/
773void quedeclar_cplx(char *instruct, char *pstr2)
774{    char    *pstr, *pmax;
775     char    bufwrk[BUFSIZE+1];
776     char    delim;
777     char    *p1;
778     char    varcplx[LG_MAX_NAME+1];
779                 short   flagvarcplx=0;
780                 //short flagisinput=0;
781                 short   idin1=-1,idin2=-1;
782
783//exemple1:         "} else { complex < double > beta ( betr , beti ) ;"
784//                            ^
785//exemple2:         "} else { complex < double > beta ( betr , beti ), alpha ( ar , ai ), gamma;"
786//                            ^
787     pstr2[-1]='\0'; //nb: le token est en principe preceded d'au moins un ' ' ou '\t'
788     //on produit le debut
789     if (instruct<pstr2)
790        BackwardOut(instruct); //d'abord le debut de l'instruction
791
792     strcpy(bufwrk, pstr2);
793     pstr = bufwrk;
794     pmax = pstr+strlen(pstr);
795     while ((p1=str_tok(pstr, " \t", &delim, pmax))!=NULL)
796     {
797                     if ((p1[0]==')' || p1[0]==';') && flagvarcplx==1)          // fin de la variable complexe precedente
798                                 {
799                                                //a la fin, si flagisinput vaut 2 alors il s'agit une variable complexe d'entree
800                                                //if (flagisinput==2)
801                                                //Si idin1 et idin2 on une valeur d'indice alors (...) : variable complexe (d'entree?)
802                                                if (idin1>=0 && idin2>=0)
803                                                {  TabFlagIn[idin1] = TabFlagIn[idin2] = -1; //on neutralise ces entrees car c'est le complexe
804                                                                ++NbInCplx;                               //associed qui devient la variable d'entree
805                                                                //idin1 = idin2 = -1;
806                                                                //flagvarcplx=0;
807                                                }
808                                                else    //sinon, il s'agit d'une variable intermediaire, on produit DAdx pour backward
809                                                {  BackProduce_DAdx(varcplx);
810                                                }
811
812                                    //re-init et passage a l'eventuelle variable suivante
813                                    flagvarcplx=0;
814                                                idin1 = idin2 = -1;
815            pstr = pstr+strlen(pstr)+1; //pour avancer sur la chaine de carateres
816                                    continue;
817                                 }
818
819               if (str_qalphanum(p1))
820            if (!c_word(p1) && !is_yadvar(p1))
821                                 {
822            if (!flagvarcplx)
823                                                {  //on est sur le 1er token apres "double",  donc c'est sense etre le
824                                                   //nom de la variable complexe beta
825
826/*xxxxxxxxx
827                                                         if (!exist_expresym(p1))
828                                                         {  if (NbExpreSym>=NB_MAX_EXPRESYM)
829                                                                        {  printf(" Ydf1: Automatic derivativ stopped for modul %s\n", ModulName);
830                                                                                        printf("       because :=> too much token in that modul\n");
831                                                                                        exit(-9);
832                                                            }
833                                                            strcpy(TabExpreSym[NbExpreSym], p1);
834                                                            ++NbExpreSym;
835                                                            fprintf(fpginac,"  ex %s;\n", p1);
836                                                            fprintf(fpginac,"  symbol Ygs_%s(\"Ygs_%s\");\n", p1, p1);
837                                                         }
838*/
839                                                         Sto_GinProduce_ExpreSym(p1);
840/*xxxxxxxxx
841//             if (!exist_cplx(p1))
842                                                   {  if (NbCplx>=NB_MAX_CPLX)
843                  {  printf(" Ydf1: Automatic derivativ stopped for modul %s\n", ModulName);
844                     printf("       because :=> too much complex token in that modul\n");
845                     exit(-9);
846                  }
847                  strcpy(TabCplx[NbCplx], p1);
848                  ++NbCplx;
849                                                         }
850*/
851                                                         strcpy(varcplx, p1); //="beta"
852                                                   flagvarcplx=1;
853                                                }
854                                                else
855                                                {  //on est sur une des variables d'entree (betr ou beti) qui forme le complexe
856                                                   //if (is_input(p1)) ++flagisinput;
857                                                         if (idin1==-1) idin1=id_input(p1);
858                                                         else idin2=id_input(p1);
859                                                }
860
861                                 }
862         pstr = pstr+strlen(pstr)+1;
863     }
864
865                 //on reconduit la suite (declaration proprement dite) tel quel pour backward
866     BackwardOut(pstr2);
867}
868
869
870/*---------------------------------------------------------------------------*/
871/*=============================================================================*/
872void queaffect(char *instruct, char *pstr2)
873{  char   *pstr3;
874   char   affectsv[BUFSIZE+1];
875
876         if (trace) printf("\n/*indicAFFECT:|%s|%s|*/\n", instruct, pstr2);
877   //des tokens d'affectation ('=', '+=', '-=', '*=', '/=')
878   //on ete detected ... et pstr2 pointe dessus printf ("|%s|\n|%s|\n", instruct, pstr2);
879         //exemple:  "} else { double ZFROZEN2 = x1 ;"
880
881   //si on a VAR {+,-,*,/}= EXPR; on va transformer en VAR = VAR {+,-,*,/} ( EXPR );
882         if (pstr2[0]=='+' || pstr2[0]=='-' || pstr2[0]=='*' || pstr2[0]=='/')
883         {  //printf("avant:|%s|%p|%c|\n", instruct, pstr2, pstr2[0]);
884            transfo_affect(instruct, pstr2); //(! modifie la chaine passed mais pstr2 doit pointer sur '=')
885      //printf("apres:|%s|%p|%c|\n", instruct, pstr2, pstr2[0]);
886         }
887
888         //si les variables sont externes au module (une variable globale par exemple)
889         //il faut quand meme la declarer pour ginac
890         Sto_GinProduce_ExpreSym(instruct);
891
892         //ensuite, on va decouper l'instruction en 3 morceaux : Debut (instruct)  Variable(pstr3) Suite(pstr2)
893   --pstr2;
894   while ((pstr2[0]==' ' || pstr2[0]=='\t') && pstr2>instruct) --pstr2; //on remonte les espaces et \t
895   pstr3=pstr2; //pstr3 va servire a pointer sur le debut de la variable affectee
896   while (pstr3[0]!=' ' && pstr3[0]!='\t' && pstr3>instruct) --pstr3; //on remonte les autres caractères
897         if (pstr3>=instruct)  //si on est pas au debut de instruct
898   {  pstr3[0]='\0'; //on met un '\0' avant la variable affected
899      ++pstr3;
900   }
901   ++pstr2; pstr2[0]='\0'; //on met un '\0' apres la variable
902   ++pstr2; //pour ne pas perdre la partie affectation de la suite de 'instruction
903   //on devrait etre dans la situation suivante: ex:  "   if ( C1 ) " "A"    " = pow ( x , 2 ) , B ; "
904         //                                                  ^instruct       ^pstr3 ^pstr2
905
906   //au passage, on interdit l'affectation des variables d'input ...!
907   if (id_input(pstr3)!=-1) //(is_input(pstr3))
908   {  printf (" Ydf1: Automatic derivative failed for modul %s\n", ModulName);
909      printf ("       because :=> input values must not be changed !\n");
910                        exit (-9);
911   }
912
913   //positionnenemt d'un flag pour savoir s'il s'agit d'un YSi
914   indicYS = id_YSi(pstr3);
915
916   //puis on produit pour backward
917         if (instruct<pstr3) BackwardOut(instruct); //d'abord le debut de l'instruction (si different de pstr3)
918   if ((indicBLOCK-indicCROUV)>0) //if (indicBLOCK && !indicCROUV)
919   {  fprintf(fpginac,"  cout << \"{\"<<endl;\n"); //et eventuellement, on rajoute un crochet ouvrant ('{')
920      ++CurBlockLev; //printf("+CurBlockLev=%i\n", CurBlockLev);
921   }
922
923   //si on a detecter un tableau on passe et on le remplace par une variable intermediaire
924         if (indicTAB) substitut_produce_tab(pstr2); // puis les tableaux s'il y a lieu (! modifie la chaine passed)
925
926         //pour ginac il faut reconduire l'affectation en remplacant les variables de la partie droite par des symbols
927   //on sauvegarde donc cette partie droite car on devra la reproduire pour backward mais seulement apres les derivee
928   strcpy(affectsv, pstr2);    //sauvegarde pour backward
929         substitut_by_symbol(pstr2); //on remplace les QAN par leur equivalent symbol(! modifie la chaine passed)
930   fprintf(fpginac,"  %s %s\n", pstr3, pstr2); //et on produit pour ginac
931
932         //maintenant, il faut calculer les derivees.
933   //1) il faut  produire dans ginac les derivee de tous les QAN de droite pour celui de gauche :
934   //   ex avec : A = f(sB, sB, sC, ...)
935   //   on doit obtenir :  da_DB = A.diff(sB,1);  UNE SEULE FOIS
936   //                                                                            da_DC = A.diff(sC,1);                  ...
937         GinBackProduce_dfDf(pstr3, affectsv);
938
939   //2) puis il faut produire dans le backward directement, la derivee du terme de gauche par rapport aux entrees.
940   //   il s'agit de faire, la somme pour chaque entree xi :
941   //             DA_dxi = dA_DV1.DV1_dxi + ... + dA_DVn.DVn_dxi
942         BackProduce_Dfdx(pstr3, affectsv);
943
944   //on termine par l'affectation pour backward (sauf pour YSi a moins que level>=9 !?)
945   if (indicYS<=0 || (indicYS>0 && prodlevel>=9))
946   {
947                        BackwardOut(pstr3);          //la variable
948      fprintf(fpginac,"  cout <<\" \";\n"); //(un espace separateur?)
949                        BackwardOut(affectsv);       //puis la suite (partie affectation prealablement sauvegarded)
950   }
951
952         //eventuellement, il faut terminer par une accolade fermante ('}')
953   if ((indicBLOCK-indicCROUV)>0) //if (indicBLOCK && !indicCROUV)
954   {  fprintf(fpginac,"  cout <<endl<< \"}\"<<endl;\n");
955      decrem_diff_blocklev(); //--CurBlockLev; //printf("+CurBlockLev=%i\n", CurBlockLev);
956   }
957}
958/*----------------------------------------------------------------------------*/
959/*============================================================================*/
960void declaretaffect (char *instruct, char *pstr2)
961{  //declaration et affectation: ex : if (... double A=vglob1, B=pow(A,2), C, D=A*vglob2;
962   //pstr2 pointe sur le type
963         char   *p3;
964         char   *paffect;
965         char   winst[BUFSIZE +1];
966         int    entre;
967         int    wi, last;
968         int    blockindic=0;
969
970   if (trace) printf("\n/*indicDECLAR & indicAFFECT:|%s|%s|*/\n", instruct, pstr2);
971
972   //on produit le debut
973         pstr2[-1]='\0'; //nb: le token est en principe preceded d'au moins un ' ' ou '\t'
974   if (instruct<pstr2) BackwardOut(instruct); //d'abord le debut de l'instruction (si different de pstr2)
975
976   //puis ici, y'a peut etre bien des crochet ....
977   if ((indicBLOCK-indicCROUV)>0) //if (indicBLOCK && !indicCROUV)
978   {  fprintf(fpginac,"  cout << \"{\"<<endl;\n"); //et eventuellement, on rajoute une accolade ouvrante ('{')
979      ++CurBlockLev; //printf("+CurBlockLev=%i\n", CurBlockLev);
980                        //et on neutralise le flag indicBLOCK pour pas avoir des accolades en double par la fct queaffect()
981            //blockindic=1; indicBLOCK=0;
982                        blockindic=indicBLOCK;  indicBLOCK=indicCROUV;
983   }
984
985         //on se positionne a la fin du type pour l'isoler
986         p3 = pstr2;
987         while (p3[0]!=' ' && p3[0]!='\t') ++p3;
988         p3[0]='\0';
989         ++p3;
990
991         //puis, on remplace toutes les ',' qui ne sont pas entre ({[]}) par ';'
992         //a partir de p3
993         entre = 0;
994         wi=0; last=0;
995         while (!last)
996         {   if (p3[wi]==';') last=1;
997
998             if (p3[wi]=='(' || p3[wi]=='{' || p3[wi]=='[') ++entre;
999             if (p3[wi]==')' || p3[wi]=='}' || p3[wi]==']') --entre;
1000                         if (p3[wi]==',' && entre==0) p3[wi]=';';
1001
1002                         if (p3[wi]==';') //il faut traiter le cas   icicicicici
1003                         {  if (!last) p3[wi+1]='\0';
1004                            if ((paffect = str_affect(p3)) != NULL)
1005                                        {  //on traite l'aspect declaration
1006                                           paffect[-1] = '\0'; //ca isole la variable
1007                                                 sprintf(winst, " %s %s ;\n", pstr2, p3); //on formate la declaration
1008                                                 quedeclar(winst, winst);                                                     //et on la traite
1009
1010                                                 //on traite l'aspect affectation
1011                                                 sprintf(winst, " %s %s \n", p3, paffect);
1012                                                 paffect = str_affect(winst);
1013                                                 queaffect(winst, paffect);
1014                                        }
1015          else // il ne s'agit que d'une declarartion
1016                                        {   sprintf(winst, " %s %s \n", pstr2, p3); //on formate la declaration
1017                                                  quedeclar(winst, winst);                                                   //et on la traite
1018                                        }
1019
1020                                        p3 = &p3[wi+2]; //equiv: p3 = p3+wi+2;
1021                                        wi = 0;
1022                         }
1023                         else
1024                            ++wi;
1025         }
1026
1027   //eventuellement, on ajoute une accolade fermante ('}') et on restaure le flag indicBLOCK
1028   if (blockindic) //(blockindic>0)
1029   {  fprintf(fpginac,"  cout <<endl<< \"}\"<<endl;\n");
1030      decrem_diff_blocklev(); //--CurBlockLev; //printf("+CurBlockLev=%i\n", CurBlockLev);
1031      indicBLOCK=blockindic; //indicBLOCK=1;
1032   }
1033
1034         //printf("\n/*indicDECLAR & indicAFFECT:|%s|%s|*/\n", instruct, pstr2);
1035}
1036
1037/*=============================================================================*/
1038/* en entree : un nom de module.h qui est sensee contenir une fonction forward */
1039/* en sortie : un programme qui saura generer une fonction backward            */
1040/*=============================================================================*/
1041/*---------------------------------------------------------------------------*/
1042int main (int argc, char *argv[])
1043{  //syntaxe: Ydf1 wrk_modul_in_file_name  module  nbin  nbout  [prodlevel]
1044        int     nbinfound=0;
1045  char    *paffect;
1046        char      *pstr1;
1047  char    *pstr2=NULL;
1048        char      modul_file_name[LG_MAX_NAME+1];
1049        int     lenmodulname;
1050  printf("Ydf1:id:3\n");
1051
1052   /* debut : verif arg, ouverture fichier ... :::::::::::::::::::::::::::::::*/
1053  if (argc < 5 || argc > 6)
1054        {  printf (" Ydf1: Syntaxe error: Ydf1 modul_file_name module_name nbin nbout [prodlevel]}\n");
1055           exit(-9);
1056        }
1057
1058        strcpy(modul_file_name, argv[1]);
1059        if ((fpmodul = fopen(modul_file_name, "r")) <= 0)
1060        {  printf (" Ydf1: In file (%s) not found \n", argv[1]);
1061           exit(-9);
1062        }
1063
1064  if (argc==6)
1065  {  prodlevel=atoi(argv[5]);
1066  }
1067
1068  NbIn  = atoi(argv[3]);
1069  NbOut = atoi(argv[4]);
1070
1071  /*-----*/
1072        if ((fpginac = fopen("Y37wrk.cc", "w")) <= 0)
1073        {  printf (" Ydf1: Pb when opening out file (Y37wrk.cc)\n");
1074           exit(-9);
1075        }
1076  /*-----*/
1077
1078        //on recupere le nom du module (pour apres)
1079        strcpy(ModulName, argv[2]);                                     //en enlevant
1080        lenmodulname = strlen(ModulName);   //eventuellement .h
1081        if (ModulName[lenmodulname-1]=='h' && ModulName[lenmodulname-2]=='.')
1082           ModulName[lenmodulname-2]='\0';
1083
1084  /* entête */
1085  fprintf (fpginac, "#include <iostream>\n");
1086  fprintf (fpginac, "#include <ginac/ginac.h>\n");
1087  fprintf (fpginac, "using namespace std;\n");
1088  fprintf (fpginac, "using namespace GiNaC;\n");
1089  fprintf (fpginac, "int main()\n");
1090  fprintf (fpginac, "{\n");
1091
1092  memset(instruct, '\0', BUFSIZE+1); //instruct[0]='\0';
1093
1094  /* boucle de lecture du module */
1095  while (  (fgets(buffer, BUFSIZE+1, fpmodul)) != NULL)
1096  {   //printf("lu|%s|\n", buffer);
1097
1098                  pstr1 = strtok(buffer, delim);
1099      while (pstr1!=NULL)
1100      {   //printf("pstr1=|%s|\n", pstr1);
1101
1102          if (!strcmp(pstr1, "{")) ++CurBlockLev;
1103          if (!strcmp(pstr1, "}")) decrem_diff_blocklev(); //--CurBlockLev; //printf("CurBlockLev=%i\n", CurBlockLev);
1104          //----------------------------------------------------------
1105          //traitement ligne forward
1106                                        //----------------------------------------------------------
1107          if (Phase==0 && !strcmp(pstr1, "forward"))
1108          {  Phase=1;
1109          }
1110          else if (Phase==1)
1111          {  if (!strcmp(pstr1, "{")) //if (pstr1[0]=='{')
1112             {
1113                if (nbinfound != NbIn)
1114                {  printf (" Ydf1: Automatic derivative failed for modul %s\n", ModulName);
1115                   printf ("       because :=> Desagree on input: found %i expected %i\n", nbinfound, NbIn);
1116                                                                         exit (-9);
1117                }
1118                fprintf(fpginac, "  cout << \"void %s::backward (", ModulName);
1119                for (k=0; k<NbIn-1; ++k)
1120                    fprintf(fpginac, "YREAL  %s, ", TabExpreSym[k] );
1121                fprintf(fpginac, "YREAL  %s ", TabExpreSym[k] );
1122                fprintf(fpginac, ")\"<<endl<<\"{\";\n");
1123
1124                Phase=2;
1125                                                                strcpy(delim," \t");  //delimiteur pour la PHASE 2
1126             }
1127             else
1128             {  //traitement ligne forward : symbole d'input
1129                if (strcmp(pstr1, "YREAL"))
1130                {  //chouette voici un symbole d'input //printf ("symbol=%s\n", pstr1);
1131                                                                         Sto_GinProduce_ExpreSym(pstr1);
1132                   ++nbinfound;
1133               }
1134             }
1135          }
1136                                        //----------------------------------------------------------
1137          // fin ligne forward, maintenant il s'agit de traiter le corps
1138                                        //----------------------------------------------------------
1139          //algo : on stock les tokens dans une chaine jusqu'a un ';'
1140                                  else if (Phase==2)
1141          {
1142                                                        //stockage (par concatenation) des tokens dans la chaine instruct
1143                                                  sprintf (instruct, "%s %s", instruct, pstr1);
1144
1145              //indicateurs ...
1146              if      (!strcmp(pstr1, "complex"))
1147              {  flagCPLX=1;
1148                                                           //ne pas casser pstr2 si deja positionned
1149                                                                 if (pstr2==NULL) //if (!indicAFFECT) //sinon il doit s'agir d'un cast
1150                                                           {  pstr2=instruct+strlen(instruct)-strlen(pstr1);
1151                                                                    indicDECLAR = 1;
1152                                                                 }
1153              }
1154              else if (!strcmp(pstr1, "if"))      ++indicBLOCK; //indicBLOCK  = 1;
1155              else if (!strcmp(pstr1, "else"))    ++indicBLOCK; //indicBLOCK  = 1;
1156              else if (!strcmp(pstr1, "while"))   ++indicBLOCK; //indicBLOCK  = 1;
1157              else if (!strcmp(pstr1, "for"))     ++indicBLOCK; //indicBLOCK  = 1;
1158              else if (!strcmp(pstr1, "{"))       ++indicCROUV; //indicCROUV  = 1;
1159              else if (strchr(pstr1, '[')!=NULL)  indicTAB    = 1;
1160              else if ( !strcmp(pstr1, "YREAL") || !strcmp(pstr1, "double")  || !strcmp(pstr1, "int")
1161              ||        !strcmp(pstr1, "long")  || !strcmp(pstr1, "float")
1162                      )
1163              {  //ne pas casser pstr2 si deja positionned
1164                                                           if (pstr2==NULL) //if (!indicAFFECT) //sinon il doit s'agir d'un cast
1165                                                           {  pstr2=instruct+strlen(instruct)-strlen(pstr1);
1166                                                                    indicDECLAR = 1;
1167                                                                 }
1168              }
1169
1170                                                        paffect = str_affect(pstr1);
1171                                                        if (paffect != NULL)
1172                                                        {  //if (!indicAFFECT && !indicDECLAR) //... ne pas casser pstr2 si deja positionned
1173                                                           if (pstr2==NULL) //... ne pas casser pstr2 si deja positionned
1174                                                           {  //pstr2 = paffect;
1175                                                                    pstr2 = instruct+strlen(instruct)-strlen(paffect);
1176                                                                 }
1177                                                           indicAFFECT = 1;
1178                                                        }
1179
1180              //au passage, on s'assurer qu'YS* n'apparait pas en partie droite
1181              //because c'est pas pratique a gerer, mais ce peut etre une source d'erreur !!!??? ...
1182              if  (indicAFFECT || indicDECLAR) //on est donc soit deja en partie droite d'une affectation,
1183              {                                //soit sur une declaration et la aussi YSi ne doit pas apparaitre
1184                                  if (id_YSi(pstr1)>0)
1185                  {  printf (" Ydf1: Automatic derivative failed for modul %s\n", ModulName);
1186                     printf ("       because :=> YSi must not appears neither on declaration or on right side of an affectation !\n");
1187                                                                           exit (-9);
1188                  }
1189              }
1190
1191                    //fin de constitution de la chaine; il faut traiter
1192              if  (!strcmp(pstr1, ";"))
1193              {
1194                  if (indicDECLAR && !indicAFFECT)  //=> SI QUE DECLAR
1195                                                                        {        if (flagCPLX)                                                                                   //ex:  " if ( C1 ) complex < double > A ( rA , iA ) ; "
1196                                                                              quedeclar_cplx(instruct, pstr2); //                           ^
1197                                                                           else //cas 'normal'
1198                                                                                    quedeclar(instruct, pstr2);   //ex:  " if ( C1 ) double A ; "
1199                                                                                                                                                                                                                  //      ^instruct  ^pstr2
1200                                                                        }
1201                  else if (indicDECLAR) //=> SI DECLAR ET AFFECT
1202                  {  declaretaffect(instruct, pstr2); //ex:  "if ( C1 )  double A = pow ( x , 2 ) , B ; "
1203                                                                        }                                   //      ^instruct  ^pstr2
1204                                                                        else if (indicAFFECT) //=> SI QUE AFFECT
1205                  {   queaffect(instruct, pstr2);     //ex:  "   if ( C1 )  A = pow ( x , 2 ) , B ; "
1206                                                                        }                                   //      ^instruct       ^pstr2
1207                  else
1208                  {  // ???!!!! reconduit-on ou pas tel quel !!!???
1209                     if (prodlevel==1 || prodlevel>2)
1210                     {  //on reproduite tel quel, QUE pour BACKWARD et donc RIEN pour GINAC.
1211                        //il doit s'agir de ce genre d'instruction dont on ne sait que faire
1212                        //pour la derivation comme *printf*, *str*, *get*, *scan*, io, ...
1213
1214                        //j'ai un pb avec les " exemple :  strcpy ( toto , "toto" ) ; ...
1215                        //ca devrait etre regled
1216                        //printf("  cout << \"%s\";\n", instruct);
1217                                                                                                BackwardOut(instruct); //par contre c'est ok pour par exemple:  strcpy(toto,titi);
1218                     }
1219                  }
1220
1221                  //re-init pour instruction suivante
1222                  indicBLOCK=indicCROUV=indicTAB=indicAFFECT=indicDECLAR=indicYS=0; //re-init des indicateurs
1223                                                                        pstr2=NULL;
1224                  memset(instruct, '\0', BUFSIZE+1); //reinit de instruct
1225              }//fin de if ';'
1226                                        }//fin du if Phase 2
1227                            //passer au token suivant
1228          pstr1 = strtok(NULL, delim);
1229     }
1230  }
1231  BackwardOut(instruct); //pour reconduire la fin du code pour backward qui peut (et
1232                         //devrait) consister des carateres de terminaison de block ('}')
1233
1234        //fprintf(fpginac, "  } \n\n", pstr2); // fin pour ginac
1235        fprintf(fpginac, "  } \n\n"); // fin pour ginac
1236  exit(0);
1237}
Note: See TracBrowser for help on using the repository browser.