home *** CD-ROM | disk | FTP | other *** search
/ BCI NET 2 / BCI NET 2.iso / archives / programming / utilities / apurify.lha / APurify / APfuncs.c next >
Encoding:
C/C++ Source or Header  |  1995-03-11  |  21.9 KB  |  1,007 lines

  1. /*
  2.  *    APfuncs.c
  3.  */
  4.  
  5. /*
  6.  *  Pourquoi 1 seul fichier de fonctions ? Bonne question ! La logique de
  7.  *  programmation habituelle (dictee par qui, le bon sens, hum ?) impose
  8.  *  de programmer structure. Cela implique l'utilisation de modules separes
  9.  *  pour chaque fonction de base.
  10.  *
  11.  *  On dit que cela permet d'avoir un code plus lisible (pourquoi pas ?).
  12.  *  Cependant, il existe un probleme dans le cadre d'une librairie de
  13.  *  foncstions. En effet certaines fonctions peuvent etre vue privee dans
  14.  *  un module (static en C). D'autres privee a la librairie. C'est a dire
  15.  *  une fonction non disponible a l'exterieur de la librairie, mais publique
  16.  *  pour chaque module de la librairie (la fonction do_print() en est un
  17.  *  exemple). Malheureusement en C il est impossible de faire un tel
  18.  *  distinguo, puisqu'il ne connait que la privaute au sein d'un module.
  19.  *
  20.  *  En C on est donc contraint a declarer ces fonctions publique. Cela pose
  21.  *  des pbs a l'utilisateur de la librairie qui peut utiliser cette fonction
  22.  *  sans connaitre son existance et provoquer des bugs (re-definition d'une
  23.  *  fonction de bibliotheque). Par exemple, la fonction t_format()
  24.  *  (_pfmtone() pour DICE) est parfois utilisee par printf() pour la sortie
  25.  *  et je vous deconseille alors d'avoir une fonction qui porte le meme nom
  26.  *  dans votre programme. La solution alors utilisee est de choisir le nom
  27.  *  des fonctions de telle sorte qu'il soit peu probable que l'utilisateur
  28.  *  choisisse un homonyme. Cepandant puisque ces fonctions ne sont pas
  29.  *  doccumentees, il n'est pas impossible que cela arrive. De plus, les
  30.  *  noms sont alors parfois prefixes d'une sequence identique (_ ou lib_
  31.  *  en general). Ainsi le code apparait beaucoup moins clair a lire:
  32.  *
  33.  *        int _lib_purify_do_print(fmt, ... )...
  34.  *        void proc_x()
  35.  *        {
  36.  *        _lib_purify_do_print("Ah que le nom de cette procedure"
  37.  *                 "est peinible a ecrire !!!!");
  38.  *        }
  39.  *
  40.  *  La solution que je choisis pour ce source c'est de tout garder dans
  41.  *  Un seul fichier et tout les static du modules sont donc les static de
  42.  *  la bibliotheque. Ca fait un peu bordelique (le code depasse 19Ko),
  43.  *  mais bon, s'il le faut, je decouperai cela un peu peut-etre (mais cela
  44.  *  ferait passer beaucoup de procedures de static a public pour presque
  45.  *  rien, donc je verrais... :-). En attendant, le code est comme ca. Ce que
  46.  *  je lui reproche le plus est qu'il pourrait etre re-organise (mais bon,
  47.  *  je travaille sur diskette avec 1Mo et j'ai pas specialement envie de
  48.  *  passer mes nuits dessus). En general, les gens qui sont tres "modules"
  49.  *  passent bcp de temps a decouper leur code alors qu'il est deja assez
  50.  *  petit. Cela fait apparaitre plein de bugs nouveaux qu'il mettent un temps
  51.  *  fou a trouver. En gros je pense que cela fait perdre bcp de temps pour
  52.  *  pas grand chose tout compte fait (c'est un peu le meme phenomene avec
  53.  *  les programmateurs "objets" qui font rammer leurs programmes a cause
  54.  *  d'un nombre d'acces a des fonctions(methodes) bcp trop grand !).
  55.  *
  56.  */
  57.  
  58. #include <stdio.h>
  59.  
  60. #define TRD(FRANCAIS, ANGLAIS)  ANGLAIS     /* which translation ? */
  61.  
  62. #define ifn(x)          if(!(x))            /* usefull define */
  63.  
  64. #define WARNING     "**** APURIFY WARNING !"
  65. #define ERROR        "**** APURIFY ERROR !"
  66.  
  67. #define LVOAllocMem    (-0xC6)
  68. #define LVOFreeMem    (-0xD2)
  69.  
  70. #define LARG_LINE    76
  71. #define MARG_LINE    8
  72.  
  73. #define CACHE_SIZE    2 /* nb chunk en cache */
  74.  
  75. extern void    *AsmAllocMem(),AsmFreeMem();
  76. extern void    *StdAlloc(),StdFree();
  77.  
  78. #define APopen    1
  79. #define APlock    2
  80. #define APwarn    4
  81.  
  82. typedef unsigned long ULONG;
  83. typedef unsigned char UBYTE;
  84.  
  85. typedef struct simplecli
  86.     {
  87.     char tab1[60];
  88.     ULONG Module;
  89.     } simplecli;
  90.  
  91. typedef struct simpletask
  92.     {
  93.     char tab[58];
  94.     ULONG BasPileTache,HautPileTache;
  95.     char tab2[62];
  96.     ULONG SegList;
  97.     char tab3[40];
  98.     ULONG CLI;
  99.     } simpletask;
  100.  
  101. static ULONG APflg=0;
  102. static simpletask *ThisTask;
  103. extern simpletask *FindTask();
  104. extern ULONG SetFunction();
  105. static ULONG MallocProc,FreeProc;
  106.  
  107. char *AP_procname=TRD("Aucune procedure !",
  108.               "No precedure !");
  109.  
  110. typedef struct pile
  111.     {
  112.     struct pile *next;
  113.     char *name;
  114.     } pile;
  115.  
  116. static pile *stack=NULL;
  117. static int cnt=0;
  118.  
  119. extern void *malloc();
  120.  
  121. typedef struct mchunk
  122.     {
  123.     struct mchunk *prev,*next;
  124.     ULONG deb,fin;            /* bornes incluses */
  125.     char *name;
  126.     UBYTE attr;
  127.     } mchunk;
  128.  
  129. #define attr_rd  1
  130. #define attr_wr  2
  131. #define attr_sys 4
  132.  
  133. static mchunk *mfirst=NULL;
  134.  
  135. static char *line;
  136.  
  137. static char *blocks(c)
  138.     mchunk *c;
  139.     {
  140.     static char buf[80];
  141.     sprintf(buf,"[0x%08x(%d) %c%c%c (%s)]",
  142.         c->deb, c->fin-c->deb+1,
  143.         c->attr & attr_rd  ? 'R':'-',
  144.         c->attr & attr_wr  ? 'W':'-',
  145.         c->attr & attr_sys ? 'S':'-',
  146.         c->name);
  147.     return buf;
  148.     }
  149.  
  150. static void do_spc(i)
  151.     int i;
  152.     {
  153.     while(i--) fputc(' ',stderr);
  154.     }
  155.  
  156. static int isspc(c)
  157.     char c;
  158.     {
  159.     return (c>0) && (c<=' ');
  160.     }
  161.  
  162. static void do_print(fmt, ...)
  163.     char *fmt;
  164.     {
  165.     ULONG *b = (&fmt) + 1;
  166.     char *s,*buff;
  167.     ifn(buff = malloc(1024)) /* 1024 suffisant ? */
  168.         {
  169.         fprintf(stderr,TRD(
  170.             WARNING" Impossible allouer memoire pour \"",
  171.             WARNING" Can't alloc memory for \""));
  172.         fprintf(stderr, fmt, b[0],b[1],b[2],b[3],b[4],b[5]);
  173.         fprintf(stderr,"\"\n");
  174.         return;
  175.         }
  176.     sprintf(buff, fmt, b[0],b[1],b[2],b[3],b[4],b[5]);
  177.     if(line)
  178.         {
  179.         if(s = malloc(1+strlen(line)+strlen(buff)))
  180.             {
  181.             strcpy(s, line);strcat(s,buff);
  182.             free(line);line = s;
  183.             }
  184.         else    fprintf(stderr,TRD(
  185.                        WARNING" Impossible allouer memoire"
  186.                        " pour \"%s\"\n",
  187.  
  188.                        WARNING" Can't alloc memory for \"%s"
  189.                        "\"\n"),
  190.                 buff);
  191.         }
  192.     else
  193.         {
  194.         if(s = malloc(1+strlen(buff)))
  195.             {
  196.             strcpy(s, buff);line = s;
  197.             }
  198.         else    fprintf(stderr,TRD(
  199.                        WARNING" Impossible allouer memoire"
  200.                        " pour \"%s\"\n",
  201.  
  202.                        WARNING" Can't alloc memory for \"%s"
  203.                        "\"\n"),
  204.                 buff);
  205.         }
  206.     free(buff);
  207.     }
  208.  
  209. static void do_dump(mg,md)
  210.     int mg,md;
  211.     {
  212.     int i,nbmot,nbcar;
  213.     char *s=line,*debut_ligne,*fin_ligne;
  214.  
  215.     md -= mg;
  216.  
  217.     while(*s)
  218.         {
  219.         /* recuperation stats pour ligne: nbmots, nbcar .. */
  220.         debut_ligne = s;
  221.         nbmot = nbcar = 0;
  222.         while(1)
  223.             {
  224.             int lenmot;
  225.             while(isspc(*s)) ++s;
  226.             fin_ligne = s;
  227.             if(!*s) break;
  228.             lenmot = 0;
  229.             while(*s && !isspc(*s)) {++s;++lenmot;}
  230.             if(nbmot + nbcar + lenmot>=md) break;
  231.             ++nbmot; nbcar += lenmot;
  232.             }
  233.         if(*s && nbmot)
  234.             {
  235.             int nbreste = 0,divi = nbmot - 1;
  236.             s = debut_ligne;
  237.             do_spc(mg);
  238.             while(nbmot)
  239.                 {
  240.                 while(isspc(*s)) ++s;
  241.                 while(*s && !isspc(*s))
  242.                     {
  243.                     fputc(*s,stderr);
  244.                     ++s;
  245.                     }
  246.                 if(--nbmot)
  247.                     {
  248.                     int i = md - nbcar + nbreste;
  249.                     do_spc(i/divi);
  250.                     nbreste = i % divi;
  251.                     }
  252.                 }
  253.             fputc('\n',stderr);
  254.             }
  255.         else if(nbmot)
  256.             {
  257.             s = debut_ligne;
  258.             do_spc(mg);
  259.             while(nbmot)
  260.                 {
  261.                 while(isspc(*s)) ++s;
  262.                 while(*s && !isspc(*s))
  263.                     {
  264.                     fputc(*s,stderr);
  265.                     ++s;
  266.                     }
  267.                 if(--nbmot) fputc(' ',stderr);
  268.                 }
  269.             fputc('\n',stderr);
  270.             }
  271.         s = fin_ligne;
  272.         }
  273.     free(line); line = NULL;
  274.     }
  275.  
  276. static mchunk *addchunk(),*addsyschunk();
  277.  
  278. static char *procname()
  279.     {
  280.     if(AP_procname) return AP_procname;
  281.     return stack?stack->name:TRD("PILE AP_procname VIDE !",
  282.                      "EMPTY AP_procname STACK !");
  283.     }
  284.  
  285. static int pile_vide()
  286.     {
  287.     if(cnt || stack) return 1;
  288.     return 0;
  289.     }
  290.  
  291. static void addsegchunk(sl,name)
  292.     ULONG sl;char *name;
  293.     {
  294.     ULONG haut,bas;
  295.  
  296.     sl <<= 2;
  297.     while(sl)
  298.         {
  299.         bas = sl-4; haut = bas + ((ULONG*)sl)[-1] - 1;
  300.         ifn(addsyschunk(bas, haut, name))
  301.             {
  302.             do_print(TRD(WARNING" Je ne peux allouer le block"
  303.                         " 0x%08x - 0x%08x (%s). Ce block"
  304.                         " ne sera pas pris en compte.",
  305.  
  306.                      WARNING" Can't alloc block 0x%08x -"
  307.                         " 0x%08x (%s). That block will"
  308.                         " be ignored."),
  309.                  bas, haut, name);
  310.             do_dump(0,LARG_LINE);
  311.             }
  312.         sl = (*(ULONG*)sl)<<2;
  313.         }
  314.     }
  315.  
  316. static void process_sys_chunk()
  317.     {
  318.     int tmp;
  319.     ULONG *sp;
  320.     mchunk *c;
  321. #ifdef    MANX
  322.     extern ULONG * _savesp;
  323.     sp = _savesp;
  324. #else
  325. #ifdef    _DCC
  326.     extern ULONG *_ExitSP;
  327.     sp = _ExitSP+11;
  328. #else
  329.     ULONG l[2];
  330.     l[1] = 1;
  331.     sp   = l;
  332. #endif
  333. #endif
  334.  
  335.     ifn(c = addsyschunk(0,1023,TRD("Vecteurs de base 680x0",
  336.                        "Basic 680x0 vectors")))
  337.         {
  338.         do_print(TRD(
  339.              WARNING" Je ne peux allouer le block representant"
  340.                 " les vecteurs de base. Ce block ne sera pas"
  341.                 " pris en compte.",
  342.  
  343.              WARNING" Can't alloc block for basic vectors. That"
  344.                 " block will be ignored."));
  345.         do_dump(0,LARG_LINE);
  346.         }
  347.     else c->attr &= ~attr_wr; /* lecture seulement...           */
  348.                   /* quoique ecriture peut-etre (qui va    */
  349.                   /* faire une indirection en ecriture       */
  350.                   /* dessus ?) */
  351.  
  352.     ifn(addsyschunk(ThisTask->BasPileTache,
  353.             ThisTask->HautPileTache - 1,
  354.             TRD("pile standard de la tache",
  355.                 "standard stack frame of task")))
  356.         {
  357.         do_print(TRD(
  358.              WARNING" Je ne peux allouer le block representant"
  359.                 " la pile de la tache. Ce block ne sera pas"
  360.                 " pris en compte: 0x%08x-0x%08x",
  361.  
  362.              WARNING" Can't alloc block for standard stack frame"
  363.                 " of task. That block will be ignored:"
  364.                 " 0x%08x-0x%08x"),
  365.  
  366.              ThisTask->BasPileTache,
  367.              ThisTask->HautPileTache - 1);
  368.         do_dump(0,LARG_LINE);
  369.         }
  370.  
  371.     if(((ULONG)&tmp < ThisTask->BasPileTache) ||
  372.        ((ULONG)&tmp > ThisTask->HautPileTache))
  373.         {
  374.         ULONG *haut = (ULONG*)((ULONG)sp + 8 - 1),
  375.               *bas  = (ULONG*)((ULONG)sp - sp[1] + 8);
  376.         ifn(addsyschunk(bas,haut,TRD(
  377.                 "pile supplementaire (CLI?) de la tache",
  378.                 "extra stack (CLI?) of task")))
  379.             {
  380.             do_print(TRD(
  381.                  WARNING" Je ne peux allouer le block"
  382.                     " representant la pile de la tache."
  383.                     " Ce block ne sera pas pris en"
  384.                     " compte: 0x%08x-0x%08x",
  385.  
  386.                  WARNING" Can't alloc block for stack of"
  387.                     " task. That block will be ignored:"
  388.                     " 0x%08x-0x%08x"),
  389.                  bas, haut);
  390.             do_dump(0,LARG_LINE);
  391.             }
  392.         }
  393.  
  394.     addsegchunk(((ULONG*)(ThisTask->SegList<<2))[3],TRD(
  395.             "segment du processus",
  396.             "segment process"));
  397.  
  398.     if(ThisTask->CLI)
  399.         { /* from CLI */
  400.         addsegchunk(((simplecli *)(ThisTask->CLI<<2))->Module,TRD(
  401.                 "segment du Module CLI",
  402.                 "segment Module CLI"));
  403.         }
  404.     }
  405.  
  406. static Warn()
  407.     {
  408.     fprintf(stderr,TRD(WARNING" Librairie non ouverte (%s)\n",
  409.                WARNING" Library not opened (%s)\n"), procname());
  410.     fprintf(stderr,TRD("Il faut ouvrir et fermer la librairie dans "
  411.                "main(). Par exemple:\n",
  412.  
  413.                "You should open the library in main(). For "
  414.                "example:\n"));
  415.     fprintf(stderr,"main(ac,av)\n");
  416.     fprintf(stderr,"    int ac; char *av[];\n");
  417.     fprintf(stderr,"    {\n");
  418.     fprintf(stderr,"    AP_Init();    /* "TRD("Ouverture librairie",
  419.                           "Opening library")" */\n");
  420.     fprintf(stderr,"    ...           /* "TRD("Code normal",
  421.                           "Your code")" */\n");
  422.     fprintf(stderr,"    AP_Close();   /* "TRD("Fermeture librairie",
  423.                           "Closing library")" */\n");
  424.     fprintf(stderr,"    }\n");
  425.     fprintf(stderr,TRD("L'execution continue sans APurify.\n",
  426.                "Execution goes on without APurify.\n"));
  427.     APflg |= APwarn;
  428.     }
  429.  
  430. void AP_Init()
  431.     {
  432.     register ULONG *tmp;
  433.     int var_sur_pile;
  434.  
  435.     APflg        = APopen|APlock;
  436.  
  437.     ThisTask    = FindTask(NULL);
  438.     mfirst        = NULL;
  439.  
  440.     Disable();
  441.     tmp        = (ULONG*)(((UBYTE*)StdAlloc)+14);
  442.     MallocProc  = SetFunction(*(ULONG*)4, LVOAllocMem, AsmAllocMem);
  443.     *tmp        = MallocProc;
  444.     tmp        = (ULONG*)(((UBYTE*)StdFree)+16);
  445.     FreeProc    = SetFunction(*(ULONG*)4, LVOFreeMem, AsmFreeMem);
  446.     *tmp        = FreeProc;
  447.     Enable();
  448.  
  449.     process_sys_chunk();
  450.  
  451.     APflg       &= ~APlock;
  452.     }
  453.  
  454. void AP_Close()
  455.     {
  456.     mchunk *c,*mc;
  457.  
  458.     APflg |= APlock;
  459.     ifn(APflg & APopen)
  460.         {
  461.         ifn(APflg & APwarn) Warn();
  462.         APflg &= ~APlock;
  463.         return;
  464.         }
  465.  
  466.     for(c=mfirst;c && (c->attr & attr_sys); c=c->next);
  467.     if(c)
  468.         {
  469.         do_print(TRD(
  470.              WARNING" Fermeture de la librairie sans"
  471.                 " desallocation du(des) block(s)"
  472.                 " suivant(s):",
  473.  
  474.              WARNING" Closing library without deallocation of"
  475.                 " the following block(s):"));
  476.         do_dump(0,LARG_LINE);
  477.         while(c)
  478.             {
  479.             do_print("- %s",blocks(c));
  480.             do_dump(MARG_LINE,LARG_LINE);
  481.             for(c=c->next;c && (c->attr & attr_sys); c=c->next);
  482.             }
  483.         }
  484.     for(c=mfirst;c;c=mc) {mc=c->next;free(c);}
  485.     mfirst = NULL;
  486.  
  487. /* warning inutile est stupide: la pile est independante de APURIFY.
  488.  * il est impossible que ca devienne vide qd on appelle AP_close(),
  489.  * par construction.
  490.     ifn(pile_vide())
  491.         {
  492.         do_print(TRD(
  493.              WARNING" Fermeture de la librairie sans etre"
  494.                 " retourne de la (des) procedure(s)"
  495.                 " suivante:",
  496.  
  497.              WARNING" Closing library without returning from the"
  498.                 " following procedure(s):"));
  499.         do_dump(0,LARG_LINE);
  500.         do
  501.             {
  502.             AP_unprotect();
  503.             do_print("- %s",procname());
  504.             do_dump(MARG_LINE,LARG_LINE);
  505.             }
  506.         while(!pile_vide());
  507.         }
  508. */
  509.     Disable();
  510.     SetFunction(*(ULONG*)4, LVOAllocMem, MallocProc);
  511.     SetFunction(*(ULONG*)4, LVOFreeMem, FreeProc);
  512.     Enable();
  513.     APflg &= ~(APlock|APopen);
  514.     }
  515.  
  516. static int chunkcmp(c1, c2)
  517.     mchunk *c1,*c2;
  518.     {
  519.     ULONG c1d,c1f,c2d,c2f;
  520.     if((c1d = c1->deb) < (c2d = c2->deb))
  521.         {
  522.         if((c1f = c1->fin) <  c2d) return -2;
  523.         if(c1f <= c2->fin) return -1;
  524.         return 3;
  525.         }
  526.     if(c1d > (c2f = c2->fin))  return 2;
  527.     if((c1f = c1->fin) <= c2f) return 0;
  528.     if(c1f > c2f) return 1;
  529.     }
  530.  
  531. /*
  532.  * dump complet des chunks... permet de voir si les listes sont bien
  533.  * ordonnees
  534.  */
  535. /*
  536. static dc()
  537.     {
  538.     mchunk *c = mfirst;
  539.     printf("dc(): ");
  540.     while(c)
  541.         {
  542.         printf("%s",blocks(c));
  543.         if(c = c->next) printf(" %d ",chunkcmp(c->prev,c));
  544.         }
  545.     printf("\n");
  546.     }
  547. /**/
  548.  
  549. static struct cache {long hit;mchunk *c;} cache[CACHE_SIZE];
  550.  
  551. static mchunk *cachehit(ck)
  552.     mchunk *ck;
  553.     { /* lecture cache */
  554.     struct cache *cc=cache;
  555.     int i;
  556.  
  557.     for(i = CACHE_SIZE + 1;--i && (cc->c);++cc) if(!chunkcmp(ck,cc->c))
  558.         {
  559.         ++(cc->hit);
  560.         return cc->c;
  561.         }
  562.     return NULL;
  563.     }
  564.  
  565. static void uncachehit(c)
  566.     mchunk *c;
  567.     { /* ecriture cache */
  568.     struct cache *cc,*cv; int i;
  569.  
  570.     cv = cache;
  571.     if(cv->c) for(cc = cv+1, i = CACHE_SIZE;--i;++cc)
  572.         {
  573.         ifn(cc->c) {cv = cc;break;}
  574.         if(cc->hit < cv->hit) cv = cc;
  575.         }
  576.     cv->c    = c;
  577.     cv->hit = 0;
  578.     }
  579.  
  580. static void cacheflush(ck)
  581.     mchunk *ck;
  582.     {
  583.     int i; struct cache *cc;
  584.  
  585.     for(cc = cache, i = CACHE_SIZE+1; --i; ++cc) ifn(cc->c - ck)
  586.         {
  587.         for(;--i;++cc) cc[0]=cc[1];
  588.         cc->c    = NULL;
  589.         cc->hit = 0;
  590.         return;
  591.         }
  592.     }
  593.  
  594. static mchunk *findchunk(ck)
  595.     mchunk *ck;
  596.     {
  597.     mchunk *c = mfirst, *pc;
  598.     int lastcmp;
  599.  
  600.     ifn(c) return NULL;
  601.  
  602.     if(pc = cachehit(ck)) return pc;
  603.  
  604.     if((lastcmp = chunkcmp(ck, c)) - 2) goto suite;
  605.  
  606.     while((pc = c->next) && !((lastcmp = chunkcmp(ck, pc)) - 2)) c = pc;
  607.  
  608.     if(pc) c = pc;
  609. suite:
  610.     ifn(lastcmp) uncachehit(c);
  611.     return c;
  612.     }
  613.  
  614. static int i_addchunk(c)
  615.     mchunk *c;
  616.     {
  617.     mchunk *d;
  618.  
  619.     ifn(d = findchunk(c)) {mfirst = c; return 1;}
  620.     switch(chunkcmp(c,d))
  621.         {
  622.         case -2:
  623.         c->next = d;
  624.         if(c->prev = d->prev) c->prev->next = c; else mfirst = c;
  625.         d->prev = c;
  626.         break;
  627.  
  628.         case 2:
  629.         c->prev = d;
  630.         if(c->next = d->next) {c->next->prev = c;}
  631.         d->next = c;
  632.         break;
  633.  
  634.         case -1:
  635.         case 0:
  636.         case 1:
  637.         case 3:
  638.         do_print(TRD(ERROR" Le block nouvellement alloue %s",
  639.                  ERROR" Newly allocated block %s"), blocks(c));
  640.         do_print(TRD(" recouvre le block deja alloue %s",
  641.                  " overlaps the already allocated block %s"),
  642.              blocks(d));
  643.         do_dump(0,LARG_LINE);
  644.         return 0;
  645.         break;
  646.         }
  647.     return 1;
  648.     }
  649.  
  650. static mchunk *addsyschunk(cd,cf,name)
  651.     ULONG cd,cf;
  652.     char *name;
  653.     {
  654.     mchunk *c;
  655.  
  656.     ifn(c = malloc(sizeof(*c))) return 0;
  657.     c->next = c->prev = NULL;
  658.     c->deb    = cd;
  659.     c->fin    = cf;
  660.     c->name = name;
  661.     c->attr = attr_rd|attr_wr|attr_sys;
  662.     ifn(i_addchunk(c)) {free(c);return NULL;} else return c;
  663.     }
  664.  
  665. static mchunk *addchunk(cd,cf)
  666.     ULONG cd,cf;
  667.     {
  668.     mchunk *c;
  669.  
  670.     ifn(c = malloc(sizeof(*c))) return 0;
  671.     c->next = c->prev = NULL;
  672.     c->deb    = cd;
  673.     c->fin    = cf;
  674.     c->name = procname();
  675.     c->attr = attr_rd|attr_wr;
  676.     ifn(i_addchunk(c)) {free(c);return NULL;} else return c;
  677.     }
  678.  
  679. static int subchunk(cd,cf)
  680.     ULONG cd,cf;
  681.     {
  682.     mchunk *c;
  683.     ifn(c = mfirst)
  684.         {
  685.         do_print(TRD(ERROR" Liberation de memoire dans %s alors"
  686.                   " qu'aucun block memoire n'est alloue",
  687.  
  688.                  ERROR" Freeing memory in %s while no memory"
  689.                   " block is allocated"),
  690.              procname());
  691.         do_dump(0,LARG_LINE);
  692.         return 0;
  693.         }
  694.     while(c && (cd > c->deb)) c = c->next;
  695.     if(c && (c->deb == cd && c->fin == cf))
  696.         {
  697.         cacheflush(c);
  698.         if(c->next)
  699.             {
  700.             c->next->prev = c->prev;
  701.             if(c->prev) c->prev->next = c->next;
  702.             else        mfirst = c->next;
  703.             free(c);
  704.             }
  705.         else
  706.             {
  707.             if(c->prev) c->prev->next = NULL;
  708.             else        mfirst = NULL;
  709.             free(c);
  710.             }
  711.         return 1;
  712.         }
  713.     do_print(TRD(ERROR" Aucun block memoire alloue ne correspond a"
  714.               " 0x%08x - 0x%08x (%s)",
  715.  
  716.              ERROR" No memory block matches 0x%08x - 0x%08x (%s)"),
  717.          cd, cf, procname());
  718.     do_dump(0,LARG_LINE);
  719.     return 0;
  720.     }
  721.  
  722. static void entre(type,c,c1,c2) /* acces entre 2 blocks */
  723.     char *type;
  724.     mchunk *c,*c1,*c2;
  725.     {
  726.     do_print(TRD(ERROR" Block %s\n",
  727.              ERROR" Block %s\n"),blocks(c));do_dump(0,LARG_LINE);
  728.  
  729.     do_print(TRD("%s illegale ",
  730.              "Illegal %s "), type);
  731.  
  732.     ifn(c1)      do_print(TRD("avant le block %s (depassement de %d"
  733.                   " octet(s))",
  734.  
  735.                   "before block %s (overstepping of %d"
  736.                   " byte(s))"),
  737.                   blocks(c2), c2->deb - c->deb);
  738.  
  739.     else ifn(c2) do_print(TRD("apres le block %s (depassement de %d"
  740.                   " octet(s))",
  741.  
  742.                   "after block %s (overstepping of %d"
  743.                   " byte(s))"),
  744.                   blocks(c1), c->fin - c1->fin);
  745.     else         {
  746.              do_print(TRD("entre les blocks ",
  747.                   "between blocks "));
  748.  
  749.              do_print(TRD("%s (depassement de %d octet(s)) et ",
  750.                   "%s (overstepping of %d byte(s)) and "),
  751.                   blocks(c1), c->deb - c1->fin);
  752.  
  753.              do_print(TRD("%s (depassement de %d octet(s))",
  754.                   "%s (overstepping of %d byte(s))"),
  755.                   blocks(c2),c->fin - c2->deb);
  756.              }
  757.     do_dump(MARG_LINE,LARG_LINE);
  758.     }
  759.  
  760. static void achev(type,c,c1)   /* a cheval sur un block */
  761.     char *type;
  762.     mchunk *c,*c1;
  763.     {
  764.     int d;
  765.     do_print(TRD(ERROR" Block %s",
  766.              ERROR" Block %s"), blocks(c));do_dump(0,LARG_LINE);
  767.     do_print(TRD("%s debordant le block %s ",
  768.              "Overstepping %s on block %s "), type, blocks(c1));
  769.     d = c1->deb - c->deb;
  770.     if(d<0) d = c1->fin - c->fin;
  771.     TRD(
  772.     {
  773.     if(d<0) do_print("a droite de %d octet(s)", -d);
  774.     else    do_print("a gauche de %d octet(s)",  d);
  775.     },
  776.     {
  777.     if(d<0) do_print("of %d byte(s) rightward", -d);
  778.     else    do_print("of %d byte(s) leftward",   d);
  779.     });
  780.     do_dump(MARG_LINE,LARG_LINE);
  781.     }
  782.  
  783. void AP_rd(pt,len)
  784.     ULONG pt,len;
  785.     {
  786.     mchunk mc,*c;
  787.     ifn(APflg & APopen) {ifn(APflg & APwarn) Warn();return;}
  788.     APflg |= APlock;
  789. /*    printf("Read : %08x-%08x par %s\n",pt,pt+len-1,procname());   /**/
  790.     mc.deb    = pt;
  791.     mc.fin    = pt + len - 1;
  792.     mc.name = procname();
  793.     mc.attr = attr_rd;
  794.     ifn(c = findchunk(&mc))
  795.         {
  796.         do_print(TRD(ERROR" Aucun block memoire alloue (%s) !",
  797.                  ERROR" No memory block allocated (%s) !"),
  798.              procname());
  799.         do_dump(0,LARG_LINE);
  800.         }
  801.     else
  802.         {
  803.         switch(chunkcmp(&mc,c))
  804.             {
  805.             case -2:
  806.             entre(TRD("Lecture","reading"), &mc, c->prev, c);
  807.             break;
  808.  
  809.             case 2:
  810.             entre(TRD("Lecture","reading"), &mc, c, c->next);
  811.             break;
  812.  
  813.             case -1:
  814.             achev(TRD("Lecture","reading"), &mc, c);
  815.             break;
  816.  
  817.             case 1:
  818.             achev(TRD("Lecture","reading"), &mc, c);
  819.             break;
  820.  
  821.             case 3:
  822.             TRD(
  823.             {
  824.             do_print(ERROR" Bizzare, erreur impossible: le block"
  825.                       " %s ",blocks(&mc));
  826.             do_print("recouvre le block %s",blocks(c));
  827.             },{
  828.             do_print(ERROR" Strange, impossible error: block %s",
  829.                  blocks(&mc));
  830.             do_print("is overlapping block %s", blocks(c));
  831.             })
  832.             do_dump(0,LARG_LINE);
  833.             break;
  834.  
  835.             case 0:
  836.             ifn((mc.attr & c->attr) == mc.attr)
  837.                 {
  838.                 do_print(TRD(ERROR" Block %s",
  839.                          ERROR" Block %s"),
  840.                      blocks(&mc));do_dump(0,LARG_LINE);
  841.                 do_print(TRD("Erreur de protection en"
  842.                          " lecture sur le block %s\n",
  843.  
  844.                          "Protection error in reading"
  845.                          " block %s\n"), blocks(c));
  846.                 do_dump(MARG_LINE,LARG_LINE);
  847.                 }
  848.             break;
  849.             }
  850.         }
  851.     APflg &= ~APlock;
  852.     }
  853.  
  854. void AP_wr(pt,len)
  855.     ULONG pt,len;
  856.     {
  857.     mchunk mc,*c;
  858.     ifn(APflg & APopen) {ifn(APflg & APwarn) Warn();return;}
  859.     APflg |= APlock;
  860. /*    printf("Write: %08x-%08x par %s\n",pt,pt+len-1,procname());   /**/
  861.     mc.deb    = pt;
  862.     mc.fin    = pt + len - 1;
  863.     mc.name = procname();
  864.     mc.attr = attr_wr;
  865.     ifn(c = findchunk(&mc))
  866.         {
  867.         do_print(TRD(ERROR" Aucun block memoire alloue (%s)",
  868.                  ERROR" No memory block allocated (%s)"),
  869.              procname());
  870.         do_dump(0,LARG_LINE);
  871.         }
  872.     else
  873.         {
  874.         switch(chunkcmp(&mc,c))
  875.             {
  876.             case -2:
  877.             entre(TRD("Ecriture","writing"), &mc, c->prev, c);
  878.             break;
  879.  
  880.             case 2:
  881.             entre(TRD("Ecriture","writing"), &mc, c, c->next);
  882.             break;
  883.  
  884.             case -1:
  885.             achev(TRD("Ecriture","writing"), &mc, c);
  886.             break;
  887.  
  888.             case 1:
  889.             achev(TRD("Ecriture","writing"), &mc, c);
  890.             break;
  891.  
  892.             case 3:
  893.             do_print(TRD(ERROR" Bizzare, erreur impossible: le"
  894.                       " block %s ",
  895.  
  896.                      ERROR" Strange, impossible error: block"
  897.                       " %s "),
  898.                  blocks(&mc));
  899.             do_print(TRD("recouvre le block %s",
  900.                      "is overlapping block %s"),
  901.                  blocks(c));
  902.             do_dump(0,LARG_LINE);
  903.             break;
  904.  
  905.             case 0:
  906.             ifn((mc.attr & c->attr) == mc.attr)
  907.                 {
  908.                 do_print(TRD(ERROR" Block %s",
  909.                          ERROR" Block %s"),
  910.                      blocks(&mc));
  911.                 do_dump(0,LARG_LINE);
  912.                 do_print(TRD("Erreur de protection en"
  913.                          " ecriture sur le block %s",
  914.  
  915.                          "Protection error in writing on"
  916.                          " block %s"),
  917.                      blocks(c));
  918.                 do_dump(MARG_LINE,LARG_LINE);
  919.                 }
  920.             break;
  921.             }
  922.         }
  923.     APflg &= ~APlock;
  924.     }
  925.  
  926. void AP_protect()
  927.     {
  928.     pile *s;
  929.     APflg |= APlock;
  930.     ifn(s = malloc(sizeof(*s))) {++cnt;goto end;}
  931.     s->next = stack;
  932.     s->name = AP_procname;
  933.     AP_procname = NULL;
  934.     stack = s;
  935. end:    APflg &= ~APlock;
  936.     }
  937.  
  938. void AP_unprotect()
  939.     {
  940.     pile *s;
  941.     APflg |= APlock;
  942.     if(cnt) --cnt;
  943.     else
  944.         {
  945.         s = stack;stack = s->next;
  946.         AP_procname = s->name;
  947.         free(s);
  948.         }
  949.     APflg &= ~APlock;
  950.     }
  951.  
  952. ULONG PubAllocMem(len, type)
  953.     register ULONG len, type;
  954.     {
  955.     register ULONG p;
  956.  
  957.     geta4();
  958.  
  959.     if((FindTask(NULL) - ThisTask)) goto normal;
  960.     ifn(APflg & APopen)
  961.         {
  962.         ifn(APflg & APwarn) Warn();
  963.         goto normal;
  964.         }
  965.     if(APflg & APlock) goto normal;
  966.  
  967.     APflg |= APlock;
  968.  
  969. /*    fprintf(stderr, "Malloc(%d,%d) par %s\n", len, type, procname());/**/
  970.  
  971.     if(p = (ULONG)StdAlloc(len, type))
  972.     ifn(addchunk(p, p + len - 1)) {StdFree(p, len);p = NULL;}
  973.  
  974. /*    dc(); /**/
  975.  
  976.     APflg &= ~APlock;
  977.     return p;
  978. normal:
  979.     return (ULONG)StdAlloc(len, type);
  980.     }
  981.  
  982. void PubFreeMem(ptr, len)
  983.     register ULONG ptr, len;
  984.     {
  985.     geta4();
  986.  
  987.     if((FindTask(NULL) - ThisTask)) goto normal;
  988.     ifn(APflg & APopen)
  989.         {
  990.         ifn(APflg & APwarn) Warn();
  991.         goto normal;
  992.         }
  993.     if(APflg & APlock) goto normal;
  994.  
  995.     APflg |= APlock;
  996.  
  997. /*    fprintf(stderr, "Free(%08x,%d) par %s\n", ptr, len, procname()); /**/
  998.  
  999.     if(subchunk(ptr, ptr + len - 1)) StdFree(ptr, len);
  1000.  
  1001.     APflg &= ~APlock;
  1002.     return;
  1003. normal:
  1004.     StdFree(ptr, len);
  1005.     }
  1006.  
  1007.