mklink.c

Go to the documentation of this file.
00001 /*
00002  * mklink -- Create "linkdep1" and "linkdep2" files from the
00003  *           "usecode" file.
00004  *
00005  * Copyright (c) 1999 Keldon Jones
00006  */
00007 
00008 #include <stdio.h>
00009 #include <stdlib.h>
00010 
00011 
00012 /* Some basic types */
00013 typedef unsigned char byte;
00014 typedef unsigned short u16b;
00015 typedef unsigned long u32b;
00016 
00017 /* Info about one usecode function */
00018 typedef struct usecode_func usecode_func;
00019 
00020 struct usecode_func
00021 {
00022   /* Location in usecode */
00023   u32b where;
00024 
00025   /* Size of function in bytes */
00026   u16b size;
00027 
00028   /* Number of called functions */
00029   u16b num_call;
00030 
00031   /* List of called functions */
00032   u16b *called;
00033 
00034   /* Have we been visited */
00035   u16b visited;
00036 };
00037 
00038 /* List of usecode functions */
00039 usecode_func functions[4096];
00040 
00041 /*
00042  * Read an unsigned 16-bit value from a file.
00043  */
00044 void read_u16b(FILE *fff, u16b *n)
00045 {
00046   u16b x;
00047   byte c;
00048 
00049   c = fgetc(fff);
00050 
00051   x = c;
00052 
00053   c = fgetc(fff);
00054 
00055   x |= c << 8;
00056 
00057   *n = x;
00058 }
00059 
00060 /*
00061  * Read an unsigned 32-bit value from a file.
00062  */
00063 void read_u32b(FILE *fff, u32b *n)
00064 {
00065   u32b x;
00066   byte c;
00067 
00068   c = fgetc(fff);
00069 
00070   x = c;
00071 
00072   c = fgetc(fff);
00073 
00074   x |= c << 8;
00075 
00076   c = fgetc(fff);
00077 
00078   x |= c << 16;
00079 
00080   c = fgetc(fff);
00081 
00082   x |= c << 24;
00083 
00084   *n = x;
00085 }
00086 
00087 /*
00088  * Write an unsigned 16-bit value to a file.
00089  */
00090 void write_u16b(FILE *fff, u16b n)
00091 {
00092   byte c;
00093 
00094   c = n & 0xFF;
00095 
00096   fputc(c, fff);
00097 
00098   n >>= 8;
00099 
00100   c = n & 0xFF;
00101 
00102   fputc(c, fff);
00103 }
00104 
00105 /*
00106  * Write an unsigned 32-bit value to a file.
00107  */
00108 void write_u32b(FILE *fff, u32b n)
00109 {
00110   byte c;
00111 
00112   c = n & 0xFF;
00113 
00114   fputc(c, fff);
00115 
00116   n >>= 8;
00117 
00118   c = n & 0xFF;
00119 
00120   fputc(c, fff);
00121 
00122   n >>= 8;
00123 
00124   c = n & 0xFF;
00125 
00126   fputc(c, fff);
00127 
00128   n >>= 8;
00129 
00130   c = n & 0xFF;
00131 
00132   fputc(c, fff);
00133 }
00134 
00135 /*
00136  * Return the sum of the sizes of all functions in this tree.
00137  */
00138 u16b get_total_size(u16b *call_tree, u16b tree_size)
00139 {
00140   usecode_func *u_ptr;
00141   u16b size = 0;
00142   int i;
00143 
00144   /* Add size of each function */
00145   for (i = 0; i < tree_size; i++)
00146   {
00147     /* Get pointer to function info */
00148     u_ptr = &functions[call_tree[i]];
00149 
00150     /* Add in size of this function */
00151     size += u_ptr->size;
00152   }
00153 
00154   /* Return total size */
00155   return size;
00156 }
00157 
00158 /*
00159  * Return a list of all functions in the call tree of the given function.
00160  *
00161  * This function is recursive.
00162  */
00163 u16b *get_tree(u16b func_num, u16b *num)
00164 {
00165   usecode_func *u_ptr;
00166   u16b *sub_tree, sub_size;
00167   u16b *our_tree, our_size;
00168   int i, j;
00169 
00170   /* Get pointer to function info */
00171   u_ptr = &functions[func_num];
00172 
00173   /* No need to return a tree */
00174   if (u_ptr->visited)
00175   {
00176     /* No tree */
00177     *num = 0;
00178 
00179     return NULL;
00180   }
00181 
00182   /* Start with ourselves */
00183   our_size = 1;
00184 
00185   /* Start array */
00186   our_tree = (u16b *)malloc(sizeof(u16b));
00187 
00188   /* Copy our number into tree */
00189   our_tree[0] = func_num;
00190 
00191   /* We've visited this function */
00192   u_ptr->visited = 1;
00193 
00194   /* Add elements from each called function */
00195   for (i = 0; i < u_ptr->num_call; i++)
00196   {
00197     /* Get the sub-tree */
00198     sub_tree = get_tree(u_ptr->called[i], &sub_size);
00199 
00200     /* No tree returned */
00201     if (!sub_size) continue;
00202 
00203     /* Increase the number in our tree */
00204     our_size += sub_size;
00205 
00206     /* Grow our tree */
00207     our_tree = (u16b *)realloc(our_tree, sizeof(u16b) * our_size);
00208 
00209     /* Copy elements from sub-tree */
00210     for (j = 0; j < sub_size; j++)
00211     {
00212       /* Copy one element */
00213       our_tree[our_size - j - 1] = sub_tree[j];
00214     }
00215 
00216     /* Destroy sub-tree */
00217     free(sub_tree);
00218   }
00219 
00220   /* Return size */
00221   *num = our_size;
00222 
00223   return our_tree;
00224 }
00225 
00226 /*
00227  * Clear the "visited" flag from each function.
00228  */
00229 void clear_visited(void)
00230 {
00231   int i;
00232 
00233   /* Clear all "visited" flags */
00234   for (i = 0; i < 4096; i++)
00235   {
00236     /* Clear this flag */
00237     functions[i].visited = 0;
00238   }
00239 }
00240 
00241 /*
00242  * Compare two function numbers.
00243  */
00244 int comp_func(const void *one, const void *two)
00245 {
00246   u16b first = *((u16b *)one);
00247   u16b second = *((u16b *)two);
00248 
00249   /* Equal */
00250   if (first == second) return 0;
00251 
00252   /* First smaller */
00253   if (first < second) return -1;
00254 
00255   /* Second smaller */
00256   return 1;
00257 }
00258 
00259 /*
00260  * Sort a function call tree and remove duplicates.
00261  */
00262 void fix_tree(u16b *tree, u16b *tree_size)
00263 {
00264   /* Just call qsort (I'm feeling lazy) */
00265   qsort(tree, *tree_size, sizeof(u16b), comp_func);
00266 }
00267 
00268 /*
00269  * Process the "usecode" file and create the two index files.
00270  */
00271 int main(void)
00272 {
00273   FILE *usecode, *linkdep1, *linkdep2;
00274   u16b func_num, data_size, max_func;
00275   u16b total_size, lnk2_written = 0;
00276   u16b *func_tree, tree_size;
00277   usecode_func *u_ptr;
00278   int i, j;
00279 
00280   /* Open the usecode file for reading */
00281   usecode = fopen("usecode", "rb");
00282 
00283   /* Check for failure */
00284   if (!usecode)
00285   {
00286     /* Error message */
00287     fprintf(stderr, "Could not open usecode!\n");
00288 
00289     /* Give up */
00290     exit(1);
00291   }
00292 
00293   /* Open the linkdep files for writing */
00294   linkdep1 = fopen("linkdep1", "wb");
00295   linkdep2 = fopen("linkdep2", "wb");
00296 
00297   /* Read the first function number */
00298   read_u16b(usecode, &func_num);
00299 
00300   /* Process the usecode file */
00301   while (!feof(usecode))
00302   {
00303     /* Get pointer to function */
00304     u_ptr = &functions[func_num];
00305 
00306     /* Remember start of function */
00307     u_ptr->where = ftell(usecode) - 2;
00308 
00309     /* Read the function size */
00310     read_u16b(usecode, &u_ptr->size);
00311 
00312     /* Read the data size */
00313     read_u16b(usecode, &data_size);
00314 
00315     /* Skip the data section */
00316     fseek(usecode, data_size, SEEK_CUR);
00317 
00318     /* Skip number of args and local vars */
00319     fseek(usecode, 4, SEEK_CUR);
00320 
00321     /* Read number of called functions */
00322     read_u16b(usecode, &u_ptr->num_call);
00323 
00324     /* Allocate space for table */
00325     u_ptr->called = (u16b *)malloc(sizeof(u16b) * u_ptr->num_call);
00326 
00327     /* Read table */
00328     for (i = 0; i < u_ptr->num_call; i++)
00329     {
00330       /* Read this entry */
00331       read_u16b(usecode, &u_ptr->called[i]);
00332     }
00333 
00334     /* Skip past end of function */
00335     fseek(usecode, u_ptr->where + u_ptr->size + 4, SEEK_SET);
00336 
00337     /* Track highest function number */
00338     max_func = func_num;
00339 
00340     /* Read the next function number */
00341     read_u16b(usecode, &func_num);
00342   }
00343 
00344   /* Write data about each function */
00345   for (i = 0; i <= max_func; i++)
00346   {
00347     /* Get pointer to function */
00348     u_ptr = &functions[i];
00349 
00350     /* Write null data for null function */
00351     if (!u_ptr->size)
00352     {
00353       /* Write nothing */
00354       write_u16b(linkdep1, lnk2_written);
00355       write_u16b(linkdep1, 0xffff);
00356 
00357       /* Go to next function */
00358       continue;
00359     }
00360 
00361     /* Get function tree */
00362     func_tree = get_tree(i, &tree_size);
00363 
00364     /* Fix up the function tree */
00365     fix_tree(func_tree, &tree_size);
00366 
00367     /* Clear visited flags */
00368     clear_visited();
00369 
00370     /* Get total size of function + all called functions */
00371     total_size = get_total_size(func_tree, tree_size);
00372 
00373     /* Write to linkdep1 */
00374     write_u16b(linkdep1, lnk2_written);
00375     write_u16b(linkdep1, total_size);
00376 
00377     /* Write each pointer */
00378     for (j = 0; j < tree_size; j++)
00379     {
00380       /* Write this pointer to linkdep2 */
00381       write_u32b(linkdep2, functions[func_tree[j]].where);
00382 
00383       /* One more pointer written */
00384       lnk2_written++;
00385     }
00386 
00387     /* Destroy the function tree */
00388     free(func_tree);
00389   }
00390 
00391   /* Write ending on linkdep1 */
00392   write_u16b(linkdep1, lnk2_written);
00393   write_u16b(linkdep1, 0);
00394 
00395   /* Close files */
00396   fclose(usecode);
00397   fclose(linkdep1);
00398   fclose(linkdep2);
00399 
00400   /* Done */
00401   return 0;
00402 }

Generated on Mon Jul 9 14:42:50 2007 for ExultEngine by  doxygen 1.5.1