sourcepawn/compiler/sclist.c
author David Anderson <dvander@alliedmods.net>
Thu Mar 15 20:44:23 2007 +0000 (2007-03-15)
changeset 619 6934bf39171e
parent 365 d830b2b0414f
child 1266 ef8dd1cddc35
permissions -rw-r--r--
random touchups that might not be so great
     1 /*  Pawn compiler  - maintenance of various lists
     2  *
     3  *  o  Name list (aliases)
     4  *  o  Include path list
     5  *  o  Macro definitions (text substitutions)
     6  *  o  Documentation tags and automatic listings
     7  *  o  Debug strings
     8  *
     9  *  Copyright (c) ITB CompuPhase, 2001-2006
    10  *
    11  *  This software is provided "as-is", without any express or implied warranty.
    12  *  In no event will the authors be held liable for any damages arising from
    13  *  the use of this software.
    14  *
    15  *  Permission is granted to anyone to use this software for any purpose,
    16  *  including commercial applications, and to alter it and redistribute it
    17  *  freely, subject to the following restrictions:
    18  *
    19  *  1.  The origin of this software must not be misrepresented; you must not
    20  *      claim that you wrote the original software. If you use this software in
    21  *      a product, an acknowledgment in the product documentation would be
    22  *      appreciated but is not required.
    23  *  2.  Altered source versions must be plainly marked as such, and must not be
    24  *      misrepresented as being the original software.
    25  *  3.  This notice may not be removed or altered from any source distribution.
    26  *
    27  *  Version: $Id$
    28  */
    29 #include <assert.h>
    30 #include <limits.h>
    31 #include <stdlib.h>
    32 #include <string.h>
    33 #include "sc.h"
    34 
    35 #if defined FORTIFY
    36   #include <alloc/fortify.h>
    37 #endif
    38 
    39 /* a "private" implementation of strdup(), so that porting
    40  * to other memory allocators becomes easier.
    41  * By S�ren Hannibal.
    42  */
    43 SC_FUNC char* duplicatestring(const char* sourcestring)
    44 {
    45   char* result=(char*)malloc(strlen(sourcestring)+1);
    46   strcpy(result,sourcestring);
    47   return result;
    48 }
    49 
    50 
    51 static stringpair *insert_stringpair(stringpair *root,char *first,char *second,int matchlength)
    52 {
    53   stringpair *cur,*pred;
    54 
    55   assert(root!=NULL);
    56   assert(first!=NULL);
    57   assert(second!=NULL);
    58   /* create a new node, and check whether all is okay */
    59   if ((cur=(stringpair*)malloc(sizeof(stringpair)))==NULL)
    60     return NULL;
    61   cur->first=duplicatestring(first);
    62   cur->second=duplicatestring(second);
    63   cur->matchlength=matchlength;
    64   if (cur->first==NULL || cur->second==NULL) {
    65     if (cur->first!=NULL)
    66       free(cur->first);
    67     if (cur->second!=NULL)
    68       free(cur->second);
    69     free(cur);
    70     return NULL;
    71   } /* if */
    72   /* link the node to the tree, find the position */
    73   for (pred=root; pred->next!=NULL && strcmp(pred->next->first,first)<0; pred=pred->next)
    74     /* nothing */;
    75   cur->next=pred->next;
    76   pred->next=cur;
    77   return cur;
    78 }
    79 
    80 static void delete_stringpairtable(stringpair *root)
    81 {
    82   stringpair *cur, *next;
    83 
    84   assert(root!=NULL);
    85   cur=root->next;
    86   while (cur!=NULL) {
    87     next=cur->next;
    88     assert(cur->first!=NULL);
    89     assert(cur->second!=NULL);
    90     free(cur->first);
    91     free(cur->second);
    92     free(cur);
    93     cur=next;
    94   } /* while */
    95   memset(root,0,sizeof(stringpair));
    96 }
    97 
    98 static stringpair *find_stringpair(stringpair *cur,char *first,int matchlength)
    99 {
   100   int result=0;
   101 
   102   assert(matchlength>0);  /* the function cannot handle zero-length comparison */
   103   assert(first!=NULL);
   104   while (cur!=NULL && result<=0) {
   105     result=(int)*cur->first - (int)*first;
   106     if (result==0 && matchlength==cur->matchlength) {
   107       result=strncmp(cur->first,first,matchlength);
   108       if (result==0)
   109         return cur;
   110     } /* if */
   111     cur=cur->next;
   112   } /* while */
   113   return NULL;
   114 }
   115 
   116 static int delete_stringpair(stringpair *root,stringpair *item)
   117 {
   118   stringpair *cur;
   119 
   120   assert(root!=NULL);
   121   cur=root;
   122   while (cur->next!=NULL) {
   123     if (cur->next==item) {
   124       cur->next=item->next;     /* unlink from list */
   125       assert(item->first!=NULL);
   126       assert(item->second!=NULL);
   127       free(item->first);
   128       free(item->second);
   129       free(item);
   130       return TRUE;
   131     } /* if */
   132     cur=cur->next;
   133   } /* while */
   134   return FALSE;
   135 }
   136 
   137 /* ----- string list functions ----------------------------------- */
   138 static stringlist *insert_string(stringlist *root,char *string)
   139 {
   140   stringlist *cur;
   141 
   142   assert(string!=NULL);
   143   if ((cur=(stringlist*)malloc(sizeof(stringlist)))==NULL)
   144     error(103);       /* insufficient memory (fatal error) */
   145   if ((cur->line=duplicatestring(string))==NULL)
   146     error(103);       /* insufficient memory (fatal error) */
   147   /* insert as "last" */
   148   assert(root!=NULL);
   149   while (root->next!=NULL)
   150     root=root->next;
   151   cur->next=root->next;
   152   root->next=cur;
   153   return cur;
   154 }
   155 
   156 static char *get_string(stringlist *root,int index)
   157 {
   158   stringlist *cur;
   159 
   160   assert(root!=NULL);
   161   cur=root->next;
   162   while (cur!=NULL && index-->0)
   163     cur=cur->next;
   164   if (cur!=NULL) {
   165     assert(cur->line!=NULL);
   166     return cur->line;
   167   } /* if */
   168   return NULL;
   169 }
   170 
   171 static int delete_string(stringlist *root,int index)
   172 {
   173   stringlist *cur,*item;
   174 
   175   assert(root!=NULL);
   176   for (cur=root; cur->next!=NULL && index>0; cur=cur->next,index--)
   177     /* nothing */;
   178   if (cur->next!=NULL) {
   179     item=cur->next;
   180     cur->next=item->next;       /* unlink from list */
   181     assert(item->line!=NULL);
   182     free(item->line);
   183     free(item);
   184     return TRUE;
   185   } /* if */
   186   return FALSE;
   187 }
   188 
   189 SC_FUNC void delete_stringtable(stringlist *root)
   190 {
   191   stringlist *cur,*next;
   192 
   193   assert(root!=NULL);
   194   cur=root->next;
   195   while (cur!=NULL) {
   196     next=cur->next;
   197     assert(cur->line!=NULL);
   198     free(cur->line);
   199     free(cur);
   200     cur=next;
   201   } /* while */
   202   memset(root,0,sizeof(stringlist));
   203 }
   204 
   205 
   206 /* ----- alias table --------------------------------------------- */
   207 static stringpair alias_tab = {NULL, NULL, NULL};   /* alias table */
   208 
   209 SC_FUNC stringpair *insert_alias(char *name,char *alias)
   210 {
   211   stringpair *cur;
   212 
   213   assert(name!=NULL);
   214   assert(strlen(name)<=sNAMEMAX);
   215   assert(alias!=NULL);
   216   assert(strlen(alias)<=sNAMEMAX);
   217   if ((cur=insert_stringpair(&alias_tab,name,alias,strlen(name)))==NULL)
   218     error(103);       /* insufficient memory (fatal error) */
   219   return cur;
   220 }
   221 
   222 SC_FUNC int lookup_alias(char *target,char *name)
   223 {
   224   stringpair *cur=find_stringpair(alias_tab.next,name,strlen(name));
   225   if (cur!=NULL) {
   226     assert(strlen(cur->second)<=sNAMEMAX);
   227     strcpy(target,cur->second);
   228   } /* if */
   229   return cur!=NULL;
   230 }
   231 
   232 SC_FUNC void delete_aliastable(void)
   233 {
   234   delete_stringpairtable(&alias_tab);
   235 }
   236 
   237 /* ----- include paths list -------------------------------------- */
   238 static stringlist includepaths = {NULL, NULL};  /* directory list for include files */
   239 
   240 SC_FUNC stringlist *insert_path(char *path)
   241 {
   242   return insert_string(&includepaths,path);
   243 }
   244 
   245 SC_FUNC char *get_path(int index)
   246 {
   247   return get_string(&includepaths,index);
   248 }
   249 
   250 SC_FUNC void delete_pathtable(void)
   251 {
   252   delete_stringtable(&includepaths);
   253   assert(includepaths.next==NULL);
   254 }
   255 
   256 
   257 /* ----- text substitution patterns ------------------------------ */
   258 #if !defined NO_DEFINE
   259 
   260 static stringpair substpair = { NULL, NULL, NULL};  /* list of substitution pairs */
   261 
   262 static stringpair *substindex['z'-PUBLIC_CHAR+1]; /* quick index to first character */
   263 static void adjustindex(char c)
   264 {
   265   stringpair *cur;
   266   assert(c>='A' && c<='Z' || c>='a' && c<='z' || c=='_' || c==PUBLIC_CHAR);
   267   assert(PUBLIC_CHAR<'A' && 'A'<'_' && '_'<'z');
   268 
   269   for (cur=substpair.next; cur!=NULL && cur->first[0]!=c; cur=cur->next)
   270     /* nothing */;
   271   substindex[(int)c-PUBLIC_CHAR]=cur;
   272 }
   273 
   274 SC_FUNC stringpair *insert_subst(char *pattern,char *substitution,int prefixlen)
   275 {
   276   stringpair *cur;
   277 
   278   assert(pattern!=NULL);
   279   assert(substitution!=NULL);
   280   if ((cur=insert_stringpair(&substpair,pattern,substitution,prefixlen))==NULL)
   281     error(103);       /* insufficient memory (fatal error) */
   282   adjustindex(*pattern);
   283   return cur;
   284 }
   285 
   286 SC_FUNC stringpair *find_subst(char *name,int length)
   287 {
   288   stringpair *item;
   289   assert(name!=NULL);
   290   assert(length>0);
   291   assert(*name>='A' && *name<='Z' || *name>='a' && *name<='z' || *name=='_' || *name==PUBLIC_CHAR);
   292   item=substindex[(int)*name-PUBLIC_CHAR];
   293   if (item!=NULL)
   294     item=find_stringpair(item,name,length);
   295   return item;
   296 }
   297 
   298 SC_FUNC int delete_subst(char *name,int length)
   299 {
   300   stringpair *item;
   301   assert(name!=NULL);
   302   assert(length>0);
   303   assert(*name>='A' && *name<='Z' || *name>='a' && *name<='z' || *name=='_' || *name==PUBLIC_CHAR);
   304   item=substindex[(int)*name-PUBLIC_CHAR];
   305   if (item!=NULL)
   306     item=find_stringpair(item,name,length);
   307   if (item==NULL)
   308     return FALSE;
   309   delete_stringpair(&substpair,item);
   310   adjustindex(*name);
   311   return TRUE;
   312 }
   313 
   314 SC_FUNC void delete_substtable(void)
   315 {
   316   int i;
   317   delete_stringpairtable(&substpair);
   318   for (i=0; i<sizeof substindex/sizeof substindex[0]; i++)
   319     substindex[i]=NULL;
   320 }
   321 
   322 #endif /* !defined NO_SUBST */
   323 
   324 
   325 /* ----- input file list ----------------------------------------- */
   326 static stringlist sourcefiles = {NULL, NULL};
   327 
   328 SC_FUNC stringlist *insert_sourcefile(char *string)
   329 {
   330   return insert_string(&sourcefiles,string);
   331 }
   332 
   333 SC_FUNC char *get_sourcefile(int index)
   334 {
   335   return get_string(&sourcefiles,index);
   336 }
   337 
   338 SC_FUNC void delete_sourcefiletable(void)
   339 {
   340   delete_stringtable(&sourcefiles);
   341   assert(sourcefiles.next==NULL);
   342 }
   343 
   344 
   345 /* ----- documentation tags -------------------------------------- */
   346 #if !defined SC_LIGHT
   347 static stringlist docstrings = {NULL, NULL};
   348 
   349 SC_FUNC stringlist *insert_docstring(char *string)
   350 {
   351   return insert_string(&docstrings,string);
   352 }
   353 
   354 SC_FUNC char *get_docstring(int index)
   355 {
   356   return get_string(&docstrings,index);
   357 }
   358 
   359 SC_FUNC void delete_docstring(int index)
   360 {
   361   delete_string(&docstrings,index);
   362 }
   363 
   364 SC_FUNC void delete_docstringtable(void)
   365 {
   366   delete_stringtable(&docstrings);
   367   assert(docstrings.next==NULL);
   368 }
   369 #endif /* !defined SC_LIGHT */
   370 
   371 
   372 /* ----- autolisting --------------------------------------------- */
   373 static stringlist autolist = {NULL, NULL};
   374 
   375 SC_FUNC stringlist *insert_autolist(char *string)
   376 {
   377   return insert_string(&autolist,string);
   378 }
   379 
   380 SC_FUNC char *get_autolist(int index)
   381 {
   382   return get_string(&autolist,index);
   383 }
   384 
   385 SC_FUNC void delete_autolisttable(void)
   386 {
   387   delete_stringtable(&autolist);
   388   assert(autolist.next==NULL);
   389 }
   390 
   391 
   392 /* ----- debug information --------------------------------------- */
   393 
   394 /* These macros are adapted from LibDGG libdgg-int64.h, see
   395  * http://www.dennougedougakkai-ndd.org/pub/libdgg/
   396  */
   397 #if defined(__STDC_VERSION__) && __STDC_VERSION__>=199901L
   398   #define __STDC_FORMAT_MACROS
   399   #define __STDC_CONSTANT_MACROS
   400   #include <inttypes.h>         /* automatically includes stdint.h */
   401 #elif (defined _MSC_VER || defined __BORLANDC__) && (defined _I64_MAX || defined HAVE_I64)
   402   #define PRId64 "I64d"
   403   #define PRIx64 "I64x"
   404 #else
   405   #define PRId64 "lld"
   406   #define PRIx64 "llx"
   407 #endif
   408 #if PAWN_CELL_SIZE==64
   409   #define PRIdC  PRId64
   410   #define PRIxC  PRIx64
   411 #elif PAWN_CELL_SIZE==32
   412   #define PRIdC  "ld"
   413   #define PRIxC  "lx"
   414 #else
   415   #define PRIdC  "d"
   416   #define PRIxC  "x"
   417 #endif
   418 
   419 static stringlist dbgstrings = {NULL, NULL};
   420 
   421 SC_FUNC stringlist *insert_dbgfile(const char *filename)
   422 {
   423 
   424   if (sc_status==statWRITE && (sc_debug & sSYMBOLIC)!=0) {
   425     char string[_MAX_PATH+40];
   426     assert(filename!=NULL);
   427     assert(strlen(filename)+40<sizeof string);
   428     sprintf(string,"F:%" PRIxC " %s",code_idx,filename);
   429     return insert_string(&dbgstrings,string);
   430   } /* if */
   431   return NULL;
   432 }
   433 
   434 SC_FUNC stringlist *insert_dbgline(int linenr)
   435 {
   436   if (sc_status==statWRITE && (sc_debug & sSYMBOLIC)!=0) {
   437     char string[40];
   438     if (linenr>0)
   439       linenr--;         /* line numbers are zero-based in the debug information */
   440     sprintf(string,"L:%" PRIxC " %x",code_idx,linenr);
   441     return insert_string(&dbgstrings,string);
   442   } /* if */
   443   return NULL;
   444 }
   445 
   446 SC_FUNC stringlist *insert_dbgsymbol(symbol *sym)
   447 {
   448   if (sc_status==statWRITE && (sc_debug & sSYMBOLIC)!=0) {
   449     char string[2*sNAMEMAX+128];
   450     char symname[2*sNAMEMAX+16];
   451 
   452     funcdisplayname(symname,sym->name);
   453     /* address tag:name codestart codeend ident vclass [tag:dim ...] */
   454     if (sym->ident==iFUNCTN) {
   455       sprintf(string,"S:%" PRIxC " %x:%s %" PRIxC " %" PRIxC " %x %x",
   456               sym->addr,sym->tag,symname,sym->addr,sym->codeaddr,sym->ident,sym->vclass);
   457     } else {
   458       sprintf(string,"S:%" PRIxC " %x:%s %" PRIxC " %" PRIxC " %x %x",
   459               sym->addr,sym->tag,symname,sym->codeaddr,code_idx,sym->ident,sym->vclass);
   460     } /* if */
   461     if (sym->ident==iARRAY || sym->ident==iREFARRAY) {
   462       #if !defined NDEBUG
   463         int count=sym->dim.array.level;
   464       #endif
   465       symbol *sub;
   466       strcat(string," [ ");
   467       for (sub=sym; sub!=NULL; sub=finddepend(sub)) {
   468         assert(sub->dim.array.level==count--);
   469         sprintf(string+strlen(string),"%x:%x ",sub->x.tags.index,sub->dim.array.length);
   470       } /* for */
   471       strcat(string,"]");
   472     } /* if */
   473 
   474     return insert_string(&dbgstrings,string);
   475   } /* if */
   476   return NULL;
   477 }
   478 
   479 SC_FUNC char *get_dbgstring(int index)
   480 {
   481   return get_string(&dbgstrings,index);
   482 }
   483 
   484 SC_FUNC void delete_dbgstringtable(void)
   485 {
   486   delete_stringtable(&dbgstrings);
   487   assert(dbgstrings.next==NULL);
   488 }