Main Page   Modules   Alphabetical List   Data Structures   File List   Data Fields  

ToyMem.c

00001 /***************************************************************************
00002                           ToyMem.c  -  Core code for the Toy Memory Manager.
00003                              -------------------
00004     begin                : Sat Jan 25 2003
00005     copyright            : (C) 2003 by Tyler Montbriand
00006     student #            : 200200370
00007     class                : CS330
00008     email                : monttyle@heavyspace.ca
00009 ***************************************************************************/
00010 
00011 #include<malloc.h>
00012 #include<string.h>
00013 #include<stdio.h>
00014 
00015 #include "ToySegment.h"
00016 #include "ToySegmentList.h"
00017 #include "ToyProcess.h"
00018 #include "ToyMemType.h"
00019 #include "ToyMem.h"
00020 #include "ToyMem_Internal.h"
00021 #include "ToyMemPage.h"
00022 #include "ToyVirtualMem.h"
00023 #include "ToyLoad.h"
00024 #include "ToySwap.h"
00025 #include "ToyParseCmd.h"
00026 
00030 const char *ErrMessages[] =
00031 {
00032   "Invalid syntax in processor input"
00033 , "Process already loaded"
00034 , "Cannot open load file"
00035 , "Load file has invalid format"
00036 , "Excess values in load file"
00037 , "Invalid instruction in load file"
00038 , "Invalid data value in load file"
00039 , "Insufficient main memory to load file"
00040 , "Address is outside of valid segments"
00041 , "Specified process does not exist"
00042 , "Insufficient privilege for PrintAllMemory"
00043 , "END command reached, parser stopped"
00044 , "Command not yet implemented"
00045 , "Insufficient heap space"
00046 , "Invalid address for FreeHeap"
00047 , "Invalid address for ReallocateHeap"
00048 , "Invalid page size"
00049 , "Paging has not been enabled"
00050 , "Insufficient privilege for EnablePaging"
00051 , NULL                                         };
00052 
00053 void TMM_VPrintMem(ToyMM *tmm, int process, int vaddr);
00054 
00059 ErrMessage_t TMM_PrintAllMemory(ToyMM *tmm)
00060 {
00061   int n;
00062 
00063   if(tmm==NULL) return(ERR_UNKNOWN);
00064 
00065   printf(LINE_RULE);
00066   printf(LINE_PREFIX"Memory Contents:\n");
00067 
00068   for(n=0; n<tmm->memSize; n++)
00069   {
00070     TMM_PrintMem(tmm,n);
00071   }
00072   
00073   printf(LINE_RULE);
00074   
00075   return(ERR_NONE);
00076 }
00077 
00082 ErrMessage_t TMM_PrintProcessTable(ToyMM *tm, int process)
00083 {
00084   int n;
00085 
00086   if((process<0)||(process>=MAX_PROCESSES))              return(ERR_UNKNOWN);
00087   else if((process!=0)&&(tm->processList[process]==NULL))return(ERR_NOPROCESS);
00088 
00089   printf(LINE_RULE);
00090   printf(LINE_PREFIX"Process Table:\n");
00091   printf(LINE_PREFIX" PID #SEG SEG1 LEN1 SEG2 LEN2 SEG3 LEN3 SEG4 LEN4\n");
00092   printf(LINE_PREFIX" --- ---- ---- ---- ---- ---- ---- ---- ---- ----\n");
00093 
00094   for(n=0; n<MAX_PROCESSES; n++)
00095   {
00096     int i=-1;
00097     int numSegs     = -1;
00098     int segSizes[4] = {-1,-1,-1,-1};
00099     int segPos[4]   = {-1,-1,-1,-1};
00100     SegList *list=NULL;
00101 
00102     if(tm->processList[n]==NULL)  continue;
00103     list=TMM_SeekSegListHead(tm->processList[n]->segments);
00104 
00105     for(numSegs=0; (list!=NULL)&&(numSegs<4); list=list->next,numSegs++ )
00106     {
00107       segSizes[numSegs]=list->seg.len;
00108       segPos[numSegs]=list->seg.pos;
00109     }
00110     printf(LINE_PREFIX"  P%1d    %1d",n,numSegs);
00111     for(i=0; i<numSegs; i++)
00112     {
00113       printf(" %4d",segPos[i]);
00114       printf(" %4d",segSizes[i]);
00115     }
00116     printf("\n");
00117   }
00118 
00119   printf(LINE_RULE);
00120 
00121   return(ERR_NONE);
00122 }
00123 
00127 ErrMessage_t TMM_PrintProcessMemory(ToyMM *tm, int process)
00128 {
00129   int n=-1;
00130   int seg=0;
00131   SegList *list=NULL;
00132 
00133   if( (process<0)||(process>=MAX_PROCESSES))  return(ERR_UNKNOWN);
00134   if(tm->processList[process]==NULL)          return(ERR_NOPROCESS);
00135 
00136   printf(LINE_RULE);
00137   printf(LINE_PREFIX"Memory Contents:\n");
00138 
00139   list=tm->processList[process]->segments;
00140   list=TMM_SeekSegListHead(list);
00141 
00142   while(list!=NULL) /*  Loop through every segment. */
00143   {
00144     if(seg==SEG_HEAP)
00145     {
00146       SegList *heap=tm->processList[process]->usedheap;
00147       while(heap!=NULL)
00148       {
00149         int hpos=0;
00150         /* Loop through every address in used heap segs */
00151         for(hpos=heap->seg.pos; hpos<(heap->seg.pos+heap->seg.len); hpos++)
00152         {                    
00153             TMM_VPrintMem(tm,process,hpos);
00154         }
00155         heap=heap->next;
00156       }
00157     }
00158     else
00159     {
00160       /*  Loop through every address in segment.  */
00161       for(n=list->seg.pos; n<(list->seg.pos+list->seg.len); n++)
00162       {
00163         /*  Attempt to print every valid memory area.
00164             Invalid ones will not be printed. */
00165         TMM_VPrintMem(tm,process,n);
00166       }
00167     }
00168     
00169     list=list->next;
00170     seg++;
00171   }
00172 
00173   printf(LINE_RULE);
00174   return(ERR_NONE);
00175 }
00176 
00181 ErrMessage_t TMM_StoreInteger(ToyMM *tm,int process,int addr,int val)
00182 {  
00183   SegList *list;
00184   int raddr=-1;
00185   int seg=SEG_CODE;
00186   
00187   if(tm->processList[process]==NULL)  return(ERR_NOPROCESS);
00188 
00189   list=tm->processList[process]->segments;
00190   list=TMM_SeekSegListHead(list);
00191 
00192   list=list->next;  /*  Segment 0 is code segment, can't put data in it */
00193   seg++;
00194 
00195   while(list!=NULL) /*  Loop through segments */
00196   {
00197     /*  Test if address resides in segment  */
00198     if( (addr>=list->seg.pos) && (addr< (list->seg.pos+list->seg.len)) )
00199     {      
00200       if(seg==SEG_HEAP)
00201       {
00202         return(TMM_StoreHeapInteger(tm,process,addr,val));
00203       }
00204 
00205       /*  Convert virtual to real address */
00206       raddr=TMM_GetRealAddress(tm,process,addr);
00207       if(raddr<0) return(ERR_UNKNOWN);      
00208 
00209       /*  Set the memory type and value */
00210       tm->mem[raddr].type=DATA_INTEGER;
00211       tm->mem[raddr].integer.value=val;
00212       return(ERR_NONE); /*  Return success  */
00213     }
00214     list=list->next;
00215     seg++;
00216   }
00217 
00218   /*  If we didn't find it, return error. */
00219   return(ERR_INVALIDADDRESS);
00220 }
00221 
00225 ErrMessage_t TMM_StoreString(ToyMM *tm, int process, int addr, const char *str)
00226 {
00227   SegList *list;
00228   int seg=SEG_CODE;
00229   int raddr=-1;
00230 
00231   if(strlen(str)>MAX_STRLEN) return(ERR_INVALIDINPUT);
00232   if(tm->processList[process]==NULL)  return(ERR_NOPROCESS);
00233 /*  else if(TMM_PagingEnabled(tm)>=0)
00234   {
00235     return(TMM_PagedStoreString(tm,process,addr,str));
00236   }*/
00237 
00238   list=tm->processList[process]->segments;
00239   list=TMM_SeekSegListHead(list);
00240 
00241   list=list->next;  /*  Segment 0 is code segment, can't put data in it */
00242   seg++;
00243 
00244   while(list!=NULL) /*  Loop through segments */
00245   {
00246     /*  Test if address resides in segment  */
00247     if( (addr>=list->seg.pos) && (addr< (list->seg.pos+list->seg.len)) )
00248     {      
00249       if(seg==SEG_HEAP)
00250       {
00251         return(TMM_StoreHeapString(tm,process,addr,str));
00252       }
00253 
00254       /*  Convert virtual to real address */
00255       raddr=TMM_GetRealAddress(tm,process,addr);
00256       if(raddr<0) return(ERR_UNKNOWN);      
00257 
00258       /*  Set the memory type and value */
00259       tm->mem[raddr].type=DATA_STRING;
00260       strcpy(tm->mem[raddr].string.value,str);
00261       return(ERR_NONE); /*  Return success  */
00262     }
00263     list=list->next;
00264     seg++;
00265   }
00266 
00267   /*  If we didn't find it, return error. */
00268   return(ERR_INVALIDADDRESS);
00269 }
00270 
00271 /******************************************************************************/
00272 
00277 ErrMessage_t TMM_TerminateProcess(ToyMM *tmm, int ID)
00278 {
00279   SegList *list;
00280 
00281   if(tmm==NULL)                   return(ERR_UNKNOWN);
00282   /*  Can't free a nonexistent process  */
00283   if(tmm->processList[ID]==NULL)  return(ERR_NOPROCESS);
00284   else if(TMM_PagingEnabled(tmm)>=0)
00285   {
00286     return(TMM_PagedTerminateProcess(tmm,ID));
00287   }  
00288 
00289   /*  Get the list and go to it's start */
00290   list=tmm->processList[ID]->segments;
00291   list=TMM_SeekSegListHead(list);
00292 
00293   /*  Loop through entire list  */
00294   while(list!=NULL)
00295   { /*  Free every segment in process */
00296     TMM_FreeSegment(tmm,list->seg.pos,list->seg.len);
00297     list=list->next;
00298   }
00299 
00300   /*  Free the segment list itself from REAL memory */
00301   if(tmm->processList[ID]->segments!=NULL)
00302     TMM_FreeSegList(tmm->processList[ID]->segments);
00303 
00304   if(tmm->processList[ID]->freeheap!=NULL)
00305     TMM_FreeSegList(tmm->processList[ID]->freeheap);
00306 
00307   if(tmm->processList[ID]->usedheap!=NULL)
00308     TMM_FreeSegList(tmm->processList[ID]->usedheap);
00309 
00310   /*  Free the process itself */
00311   free(tmm->processList[ID]);
00312 
00313   /*  Mark the process slot as empty  */
00314   tmm->processList[ID]=NULL;
00315 
00316   return(ERR_NONE);
00317 }
00318 
00322 ErrMessage_t TMM_AllocateProcessAt(ToyMM *tmm, int ID, int pos, int nSegs, int size[])
00323 {
00324   int n=-1,startpos=-1;
00325   Process *p=NULL;
00326   SegList *list=NULL;
00327 
00328   if((ID>=MAX_PROCESSES)||(ID<0)) return(ERR_UNKNOWN);
00329   if(tmm->processList[ID]!=NULL)  return(ERR_NOPROCESS);
00330  
00331   p=(Process *)malloc(sizeof(Process));
00332   if(p==NULL) return(ERR_UNKNOWN);
00333 
00334   p->ptr=NULL;
00335   p->freeheap=NULL;
00336   p->usedheap=NULL;
00337   p->segments=NULL;
00338   p->ID=ID;
00339   p->pagetable=NULL;
00340 
00341   /*  Add the process in the memory manager */
00342   tmm->processList[ID]=p;
00343 
00344   /*  check for overlapping memory areas  */
00345   for(n=0,startpos=pos; n<nSegs; n++)
00346   {
00347     SegList *node=NULL;
00348 
00349     /*  Try and create a new segment at specified pos */
00350     if(TMM_AllocateSegmentAt(tmm,startpos,size[n])!=ERR_NONE)
00351     {
00352       /*  Free p and all it's segments  */
00353       TMM_TerminateProcess(tmm,ID);
00354       return(ERR_INSUFFICIENTMEM);
00355     }
00356 
00357     /*  Create a node representing the new segment  */
00358     node=TMM_CreateSegList(startpos,size[n],NULL,NULL);
00359 
00360     /*  Add it to the list of valid segs in p */
00361     p->segments=TMM_AppendSegList(p->segments,node);
00362 
00363     /*  Increment starting position for next segment */
00364     startpos+=size[n];
00365   }
00366 
00367   /*  Seek to the head of the list  */
00368   p->segments=TMM_SeekSegListHead(p->segments);
00369 
00370   list=TMM_GetSegmentNode(tmm,ID,SEG_HEAP);
00371   if(list!=NULL)  /* If a heap segment exists for this process */
00372   {    /* This node represents free memory in the heap segment */
00373     SegList *node=TMM_CreateSegList(list->seg.pos,list->seg.len,NULL,NULL);
00374     p->freeheap=node;
00375     p->ptr=p->freeheap;
00376   }
00377 
00378   return(ERR_NONE);    /*  Yay!  It worked!  */
00379 }
00380 
00384 ErrMessage_t TMM_AllocateSegmentAt(ToyMM *tmm, int pos, int size)
00385 {
00386   int i=-1,overlap=0;
00387   ToySegment mySeg;
00388   mySeg.pos=pos;
00389   mySeg.len=size;
00390 
00391   /*  Test for out-of-range mem */
00392   if((pos+size)>tmm->memSize)  return(ERR_INSUFFICIENTMEM);
00393 
00394   /*  Test for overlapping segments */
00395   for(i=0,overlap=0; (i<MAX_PROCESSES)&&(overlap==0); i++)
00396   {
00397     SegList *list=NULL;
00398     /*  Don't check nonexistent processes */
00399     if(tmm->processList[i]!=NULL) list=tmm->processList[i]->segments;
00400     while(list!=NULL)
00401     {
00402       ToySegment seg;
00403       /* Translate virtual segment to real segment */
00404       seg.pos=TMM_GetRealAddress(tmm,i,list->seg.pos);
00405       seg.len=TMM_GetFramedSize(tmm,list->seg.len);
00406       
00407       overlap|=TMM_AreaIntersectsSeg(&mySeg,&seg);
00408       list=list->next;
00409     }
00410   }
00411 
00412   if(overlap!=0)
00413   {
00414     return(ERR_INSUFFICIENTMEM); /*  memory range not free */
00415   }
00416   else
00417   {
00418     /*  Clear the memory so we can see what's been used */
00419     for(i=pos; i<(pos+size); i++) tmm->mem[i].type=DATA_ERROR;
00420     tmm->memFree=TMM_RemoveAreaFromSegList(tmm->memFree,pos,size);
00421     return(ERR_NONE);
00422   }
00423 }
00424 
00428 ErrMessage_t TMM_FreeSegment(ToyMM *tmm, int pos, int size)
00429 {
00430   int n;
00431   SegList *list;
00432 
00433   for(n=0; n<MAX_PROCESSES; n++)
00434   {
00435     if(tmm->processList[n]==NULL)       continue;
00436 
00437     list=tmm->processList[n]->segments;
00438     while(list!=NULL)
00439     {
00440       if((list->seg.len==size)&&(list->seg.pos==pos))
00441       {
00442         list=TMM_AddAreaToSegList(tmm->memFree,pos,size);
00443         if(list==NULL)
00444         {
00445           /* Error in deallocation */
00446           return(ERR_UNKNOWN);
00447         }
00448         else
00449         {
00450           tmm->memFree=list;
00451           return(ERR_NONE);
00452         }
00453       }
00454 
00455       list=list->next;
00456     }
00457   }
00458   /* Couldn't find it. */
00459   return(ERR_UNKNOWN);
00460 }
00461 
00462 
00466 ToyMM *TMM_Create(int memSize)
00467 {
00468   int n;
00469 
00470   ToyMM *tmm = (ToyMM *)malloc(sizeof(ToyMM));
00471 
00472   if(tmm==NULL) /*  Out of memory */
00473   {
00474     return(NULL);
00475   }
00476   else
00477   {
00478     for(n=0; n<MAX_PROCESSES; n++)
00479     {
00480       tmm->processList[n]=NULL;
00481     }
00482 
00483     /*  Starts in Legacy mode, no paging */
00484     tmm->pageSize=0;
00485     tmm->invPageTable=NULL;
00486     tmm->page=0;
00487     tmm->swap=NULL;
00488     tmm->watchPaging=0;
00489 
00490     /*  Allocate memory elements */
00491     tmm->mem=(ToyMem *)malloc(memSize*sizeof(ToyMem));
00492     tmm->memSize = memSize;    
00493 
00494     /*  Mark memory elements as empty */
00495     for(n=0; n<memSize; n++)
00496     {
00497       tmm->mem[n].type=DATA_ERROR;
00498     }
00499 
00500     /* Create free list */
00501     tmm->memFree = TMM_CreateSegList(0,memSize,NULL,NULL);
00502     
00503     /* Return new memory manager */
00504     return(tmm);
00505   }
00506 }
00507 
00511 ErrMessage_t TMM_Free(ToyMM *tmm)
00512 {
00513   int n;
00514 
00515   if(tmm==NULL) return(ERR_UNKNOWN);
00516 
00517   /*  Kill all processes  */
00518   for(n=0; n<MAX_PROCESSES; n++)
00519   {
00520     if(tmm->processList[n])
00521     {
00522       if(TMM_PagingEnabled(tmm) )      {
00523         TMM_PagedTerminateProcess(tmm,n);
00524       }
00525       else
00526       {
00527         TMM_TerminateProcess(tmm,n);        
00528       }
00529     }
00530   }
00531 
00532   /*  Free page table, if any */
00533   if(tmm->invPageTable!=NULL)
00534   {
00535     free(tmm->invPageTable);    
00536   }
00537 
00538   /* Destroy swap file, if any */
00539   TMM_SwapDestroy(tmm);
00540 
00541   free(tmm->mem);
00542   TMM_FreeSegList(tmm->memFree);
00543 
00544   return(ERR_NONE);
00545 }
00546 
00554 void TMM_VPrintMem(ToyMM *tmm, int process, int vaddr)
00555 {
00556   ToyMem *mem=NULL;
00557   int raddr=TMM_GetRealAddress(tmm,process,vaddr);
00558   if(raddr<0) return;
00559 
00560   mem=tmm->mem+raddr;
00561 
00562   if(mem->type==DATA_ERROR) return;
00563 
00564   printf(LINE_PREFIX" %3d ",vaddr);
00565   
00566   switch(mem->type)
00567   {
00568   case DATA_ERROR:
00569     break;
00570 
00571   case DATA_INTEGER:
00572     printf("%d\n",mem->integer.value);
00573     break;
00574   case DATA_INSTRUCTION:
00575     printf("%s\n",DataType_List[DATA_INSTRUCTION][mem->instruction.value]);
00576     break;
00577   case DATA_STRING:
00578     printf("%s\n",mem->string.value);
00579     break;
00580 
00581   default:
00582 
00583     printf("Unknown mem type %d, ",mem->type);
00584     printf("Email me at monttyle@heavyspace.ca and tell me how you did this.\n");
00585     break;
00586   }  
00587 }
00588 
00595 void TMM_PrintMem(ToyMM *tmm, int addr)
00596 {
00597   ToyMem *mem=tmm->mem+addr;
00598 
00599 
00600   if(mem->type==DATA_ERROR) return;
00601 
00602   printf(LINE_PREFIX" %3d ",addr);
00603   switch(mem->type)
00604   {
00605   case DATA_ERROR:
00606     break;
00607 
00608   case DATA_INTEGER:
00609     printf("%d\n",mem->integer.value);
00610     break;
00611   case DATA_INSTRUCTION:
00612     printf("%s\n",DataType_List[DATA_INSTRUCTION][mem->instruction.value]);
00613     break;
00614   case DATA_STRING:
00615     printf("%s\n",mem->string.value);
00616     break;
00617 
00618   default:
00619 
00620     printf("Unknown mem type %d, ",mem->type);
00621     printf("Email me at monttyle@heavyspace.ca and tell me how you did this.\n");
00622     break;
00623   }
00624 }
00625 
00630 SegList *TMM_GetSegmentNode(ToyMM *tm, int process, SegType_e sg)
00631 {
00632   SegList *list;
00633   int seg=sg;
00634 
00635   if((process<0)||(process>=MAX_PROCESSES)) return(NULL);
00636   if(seg<0)                                 return(NULL);
00637   if(tm->processList[process]==NULL)        return(NULL);
00638 
00639   list=TMM_SeekSegListHead(tm->processList[process]->segments);
00640 
00641   while((list!=NULL)&&(seg>0))
00642   {
00643     seg--;
00644     list=list->next;
00645   }
00646 
00647   return(list);
00648 }
00649 
00651 int TMM_GetSegmentAddr(ToyMM *tm, int process, SegType_e seg)
00652 {
00653   SegList *list=TMM_GetSegmentNode(tm,process,seg);
00654 
00655   if(list!=NULL)  return(list->seg.pos);
00656   else            return(-1);
00657 }
00658 
00662 ErrMessage_t TMM_MarkMemEmpty(ToyMM *tmm,int addr, int len)
00663 {
00664   int n;
00665   for(n=addr; n<(addr+len); n++)
00666   {
00667     tmm->mem[n].type=DATA_ERROR;
00668   }
00669   return(ERR_NONE);
00670 }
00671 
00675 ErrMessage_t TMM_CopyMem(ToyMM *tmm, int destaddr, int srcaddr, int len)
00676 {
00677   if(tmm==NULL)  return(ERR_UNKNOWN);
00678 
00679   while(len>0)
00680   {
00681     tmm->mem[destaddr++]=tmm->mem[srcaddr++];
00682     len--;
00683   }
00684   return(ERR_NONE);
00685 }
00686 
00687 int TMM_FindFreeMem(ToyMM *tmm, int size)
00688 {
00689   SegList *list=NULL;
00690 
00691   if(tmm==NULL)                       return(-1);
00692   list=tmm->memFree;
00693 
00694   while(list!=NULL)
00695   {
00696     if(list->seg.len>=size)  return(list->seg.pos);
00697 
00698     list=list->next;
00699   }
00700 
00701   return(-1);
00702 }
00703 
00704 Process *TMM_GetProcess(ToyMM *tmm, int process)
00705 {
00706   if(tmm==NULL)                           return(NULL);
00707   else if(process<0)                      return(NULL);
00708   else if(process>=MAX_PROCESSES)         return(NULL);
00709   else return(tmm->processList[process]);
00710 }
00711 
00712 int TMM_ParseFilePtr(FILE *fp, ToyMM *tm, int prompt)
00713 {
00714   int line=0;
00715   char buf[160]; /* ={'\0'}; */
00716   ErrMessage_t error=ERR_UNKNOWN;
00717   
00718   buf[0]='\0';  /* Mark buffer as empty */
00719 
00720   if(fp==NULL)  return(-1);   /*  NULL file pointer, return error   */
00721 
00722   if(prompt)  printf(TMM_CONSOLE_PROMPT,line+1);  
00723   fgets(buf,160,fp);    /*  Read first line  */
00724 
00725   /*  Ignore blank lines  */
00726   if(strlen(buf)>1) error=TMM_ParseLine(buf,tm,++line);    /*  Parse line  */
00727   else              error=ERR_NONE;
00728 
00729   do  /*  Loop until we've read it all  */
00730   {
00731     if(error!=ERR_NONE)     /*  if the line caused an error */
00732     {
00733       if(error==ERR_UNKNOWN)
00734       {
00735         /*  Unknown errors have no string in the error table.  */
00736         printf(ERR_PREFIX"Unknown error.\n");
00737       }
00738       else
00739       {
00740         /*  But other errors do.  */
00741         PRINT_ERROR(error);
00742       }
00743       if(error==ERR_PARSEEND) /*  END command, stop parsing */
00744       {
00745         fclose(fp);
00746         return(-1);
00747       }
00748     }
00749     buf[0]='\0';        /*  Empty the buffer  */
00750     
00751     if(prompt)  printf(TMM_CONSOLE_PROMPT,line+1);    
00752     fgets(buf,160,fp);  /*  Read line         */
00753 
00754     /*  Ignore blank lines  */
00755     if(strlen(buf)>1) error=TMM_ParseLine(buf,tm,++line);    /*  Parse line  */
00756     else              error=ERR_NONE;
00757   }
00758   while(!feof(fp));     /*  Loop until end-of-file  */
00759 
00760   /*  Print the last error, if any  */
00761   if(error!=ERR_NONE)
00762   {
00763       if(error==ERR_UNKNOWN)
00764       {
00765         /*  Unknown errors have no string in the error table.  */
00766         printf(ERR_PREFIX"Unknown error.\n");
00767       }
00768       else
00769       {
00770         /*  But other errors do.  */
00771         printf(ERR_PREFIX"%s\n",ErrMessages[error]);
00772       }
00773   }
00774   
00775   return(0);  /*  Return success. */
00776 }
00777 
00779 int TMM_ParseFile(const char *fname, ToyMM *tm)
00780 {
00781   int retval=-1;
00782   FILE *fp=NULL;
00783 
00784   fp=fopen(fname,"r");        /*  Open specified file for textmode reading  */
00785   if(fp==NULL)  return(-1);   /*  If we didn't get the file, return error   */
00786 
00787   retval=TMM_ParseFilePtr(fp,tm,0);
00788 
00789   fclose(fp);           /*  Close the file  */
00790 
00791   return(retval);  /*  Return success. */
00792 }

Generated on Fri Apr 4 14:29:07 2003 for ToyMem by doxygen1.3-rc3