sourcepawn/compiler/sclist.c
author David Anderson <dvander@alliedmods.net>
Sun Nov 25 18:50:13 2007 +0000 (2007-11-25)
changeset 1725 ea875bcbc286
parent 1267 13d77c75c6b9
permissions -rw-r--r--
small clarification to param2 in MenuAction_End
     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 #include "lstring.h"
    35 
    36 #if defined FORTIFY
    37   #include <alloc/fortify.h>
    38 #endif
    39 
    40 /* a "private" implementation of strdup(), so that porting
    41  * to other memory allocators becomes easier.
    42  * By S�ren Hannibal.
    43  */
    44 SC_FUNC char* duplicatestring(const char* sourcestring)
    45 {
    46   char* result=(char*)malloc(strlen(sourcestring)+1);
    47   strcpy(result,sourcestring);
    48   return result;
    49 }
    50 
    51 
    52 static stringpair *insert_stringpair(stringpair *root,char *first,char *second,int matchlength)
    53 {
    54   stringpair *cur,*pred;
    55 
    56   assert(root!=NULL);
    57   assert(first!=NULL);
    58   assert(second!=NULL);
    59   /* create a new node, and check whether all is okay */
    60   if ((cur=(stringpair*)malloc(sizeof(stringpair)))==NULL)
    61     return NULL;
    62   cur->first=duplicatestring(first);
    63   cur->second=duplicatestring(second);
    64   cur->matchlength=matchlength;
    65   cur->documentation=NULL;
    66   if (cur->first==NULL || cur->second==NULL) {
    67     if (cur->first!=NULL)
    68       free(cur->first);
    69     if (cur->second!=NULL)
    70       free(cur->second);
    71     free(cur);
    72     return NULL;
    73   } /* if */
    74   /* link the node to the tree, find the position */
    75   for (pred=root; pred->next!=NULL && strcmp(pred->next->first,first)<0; pred=pred->next)
    76     /* nothing */;
    77   cur->next=pred->next;
    78   pred->next=cur;
    79   return cur;
    80 }
    81 
    82 static void delete_stringpairtable(stringpair *root)
    83 {
    84   stringpair *cur, *next;
    85 
    86   assert(root!=NULL);
    87   cur=root->next;
    88   while (cur!=NULL) {
    89     next=cur->next;
    90     assert(cur->first!=NULL);
    91     assert(cur->second!=NULL);
    92     free(cur->first);
    93     free(cur->second);
    94     free(cur);
    95     cur=next;
    96   } /* while */
    97   memset(root,0,sizeof(stringpair));
    98 }
    99 
   100 static stringpair *find_stringpair(stringpair *cur,char *first,int matchlength)
   101 {
   102   int result=0;
   103 
   104   assert(matchlength>0);  /* the function cannot handle zero-length comparison */
   105   assert(first!=NULL);
   106   while (cur!=NULL && result<=0) {
   107     result=(int)*cur->first - (int)*first;
   108     if (result==0 && matchlength==cur->matchlength) {
   109       result=strncmp(cur->first,first,matchlength);
   110       if (result==0)
   111         return cur;
   112     } /* if */
   113     cur=cur->next;
   114   } /* while */
   115   return NULL;
   116 }
   117 
   118 static int delete_stringpair(stringpair *root,stringpair *item)
   119 {
   120   stringpair *cur;
   121 
   122   assert(root!=NULL);
   123   cur=root;
   124   while (cur->next!=NULL) {
   125     if (cur->next==item) {
   126       cur->next=item->next;     /* unlink from list */
   127       assert(item->first!=NULL);
   128       assert(item->second!=NULL);
   129       free(item->first);
   130       free(item->second);
   131       free(item);
   132       return TRUE;
   133     } /* if */
   134     cur=cur->next;
   135   } /* while */
   136   return FALSE;
   137 }
   138 
   139 /* ----- string list functions ----------------------------------- */
   140 static stringlist *insert_string(stringlist *root,char *string)
   141 {
   142   stringlist *cur;
   143 
   144   assert(string!=NULL);
   145   if ((cur=(stringlist*)malloc(sizeof(stringlist)))==NULL)
   146     error(103);       /* insufficient memory (fatal error) */
   147   if ((cur->line=duplicatestring(string))==NULL)
   148     error(103);       /* insufficient memory (fatal error) */
   149   /* insert as "last" */
   150   assert(root!=NULL);
   151   while (root->next!=NULL)
   152     root=root->next;
   153   cur->next=root->next;
   154   root->next=cur;
   155   return cur;
   156 }
   157 
   158 static char *get_string(stringlist *root,int index)
   159 {
   160   stringlist *cur;
   161 
   162   assert(root!=NULL);
   163   cur=root->next;
   164   while (cur!=NULL && index-->0)
   165     cur=cur->next;
   166   if (cur!=NULL) {
   167     assert(cur->line!=NULL);
   168     return cur->line;
   169   } /* if */
   170   return NULL;
   171 }
   172 
   173 static int delete_string(stringlist *root,int index)
   174 {
   175   stringlist *cur,*item;
   176 
   177   assert(root!=NULL);
   178   for (cur=root; cur->next!=NULL && index>0; cur=cur->next,index--)
   179     /* nothing */;
   180   if (cur->next!=NULL) {
   181     item=cur->next;
   182     cur->next=item->next;       /* unlink from list */
   183     assert(item->line!=NULL);
   184     free(item->line);
   185     free(item);
   186     return TRUE;
   187   } /* if */
   188   return FALSE;
   189 }
   190 
   191 SC_FUNC void delete_stringtable(stringlist *root)
   192 {
   193   stringlist *cur,*next;
   194 
   195   assert(root!=NULL);
   196   cur=root->next;
   197   while (cur!=NULL) {
   198     next=cur->next;
   199     assert(cur->line!=NULL);
   200     free(cur->line);
   201     free(cur);
   202     cur=next;
   203   } /* while */
   204   memset(root,0,sizeof(stringlist));
   205 }
   206 
   207 
   208 /* ----- alias table --------------------------------------------- */
   209 static stringpair alias_tab = {NULL, NULL, NULL};   /* alias table */
   210 
   211 SC_FUNC stringpair *insert_alias(char *name,char *alias)
   212 {
   213   stringpair *cur;
   214 
   215   assert(name!=NULL);
   216   assert(strlen(name)<=sNAMEMAX);
   217   assert(alias!=NULL);
   218   assert(strlen(alias)<=sNAMEMAX);
   219   if ((cur=insert_stringpair(&alias_tab,name,alias,strlen(name)))==NULL)
   220     error(103);       /* insufficient memory (fatal error) */
   221   return cur;
   222 }
   223 
   224 SC_FUNC int lookup_alias(char *target,char *name)
   225 {
   226   stringpair *cur=find_stringpair(alias_tab.next,name,strlen(name));
   227   if (cur!=NULL) {
   228     assert(strlen(cur->second)<=sNAMEMAX);
   229     strcpy(target,cur->second);
   230   } /* if */
   231   return cur!=NULL;
   232 }
   233 
   234 SC_FUNC void delete_aliastable(void)
   235 {
   236   delete_stringpairtable(&alias_tab);
   237 }
   238 
   239 /* ----- include paths list -------------------------------------- */
   240 static stringlist includepaths = {NULL, NULL};  /* directory list for include files */
   241 
   242 SC_FUNC stringlist *insert_path(char *path)
   243 {
   244   return insert_string(&includepaths,path);
   245 }
   246 
   247 SC_FUNC char *get_path(int index)
   248 {
   249   return get_string(&includepaths,index);
   250 }
   251 
   252 SC_FUNC void delete_pathtable(void)
   253 {
   254   delete_stringtable(&includepaths);
   255   assert(includepaths.next==NULL);
   256 }
   257 
   258 
   259 /* ----- text substitution patterns ------------------------------ */
   260 #if !defined NO_DEFINE
   261 
   262 static stringpair substpair = { NULL, NULL, NULL};  /* list of substitution pairs */
   263 
   264 static stringpair *substindex['z'-PUBLIC_CHAR+1]; /* quick index to first character */
   265 static void adjustindex(char c)
   266 {
   267   stringpair *cur;
   268   assert(c>='A' && c<='Z' || c>='a' && c<='z' || c=='_' || c==PUBLIC_CHAR);
   269   assert(PUBLIC_CHAR<'A' && 'A'<'_' && '_'<'z');
   270 
   271   for (cur=substpair.next; cur!=NULL && cur->first[0]!=c; cur=cur->next)
   272     /* nothing */;
   273   substindex[(int)c-PUBLIC_CHAR]=cur;
   274 }
   275 
   276 SC_FUNC stringpair *insert_subst(char *pattern,char *substitution,int prefixlen)
   277 {
   278   stringpair *cur;
   279 
   280   assert(pattern!=NULL);
   281   assert(substitution!=NULL);
   282   if ((cur=insert_stringpair(&substpair,pattern,substitution,prefixlen))==NULL)
   283     error(103);       /* insufficient memory (fatal error) */
   284   adjustindex(*pattern);
   285 
   286   if (pc_deprecate!=NULL) {
   287 	  assert(cur!=NULL);
   288 	  cur->flags|=flgDEPRECATED;
   289 	  if (sc_status==statWRITE) {
   290 		  if (cur->documentation!=NULL) {
   291 			  free(cur->documentation);
   292 			  cur->documentation=NULL;
   293 		  } /* if */
   294 		  cur->documentation=pc_deprecate;
   295 	  } else {
   296 		  free(pc_deprecate);
   297 	  } /* if */
   298 	  pc_deprecate=NULL;
   299   } else {
   300 	  cur->flags = 0;
   301 	  cur->documentation = NULL;
   302   } /* if */
   303 
   304   return cur;
   305 }
   306 
   307 SC_FUNC stringpair *find_subst(char *name,int length)
   308 {
   309   stringpair *item;
   310   assert(name!=NULL);
   311   assert(length>0);
   312   assert(*name>='A' && *name<='Z' || *name>='a' && *name<='z' || *name=='_' || *name==PUBLIC_CHAR);
   313   item=substindex[(int)*name-PUBLIC_CHAR];
   314   if (item!=NULL)
   315     item=find_stringpair(item,name,length);
   316 
   317   if (item && (item->flags & flgDEPRECATED) != 0)
   318   {
   319     static char macro[128];
   320     char *rem, *msg = (item->documentation != NULL) ? item->documentation : "";
   321     strlcpy(macro, item->first, sizeof(macro));
   322 
   323     /* If macro contains an opening parentheses and a percent sign, then assume that
   324      * it takes arguments and remove them from the warning message.
   325      */
   326     if ((rem = strchr(macro, '(')) != NULL && strchr(macro, '%') > rem)
   327     {
   328       *rem = '\0';
   329     }
   330 
   331     error(234, macro, msg);  /* deprecated (macro/constant) */
   332   }
   333   return item;
   334 }
   335 
   336 SC_FUNC int delete_subst(char *name,int length)
   337 {
   338   stringpair *item;
   339   assert(name!=NULL);
   340   assert(length>0);
   341   assert(*name>='A' && *name<='Z' || *name>='a' && *name<='z' || *name=='_' || *name==PUBLIC_CHAR);
   342   item=substindex[(int)*name-PUBLIC_CHAR];
   343   if (item!=NULL)
   344     item=find_stringpair(item,name,length);
   345   if (item==NULL)
   346     return FALSE;
   347   if (item->documentation)
   348   {
   349     free(item->documentation);
   350     item->documentation=NULL;
   351   }
   352   delete_stringpair(&substpair,item);
   353   adjustindex(*name);
   354   return TRUE;
   355 }
   356 
   357 SC_FUNC void delete_substtable(void)
   358 {
   359   int i;
   360   delete_stringpairtable(&substpair);
   361   for (i=0; i<sizeof substindex/sizeof substindex[0]; i++)
   362     substindex[i]=NULL;
   363 }
   364 
   365 #endif /* !defined NO_SUBST */
   366 
   367 
   368 /* ----- input file list ----------------------------------------- */
   369 static stringlist sourcefiles = {NULL, NULL};
   370 
   371 SC_FUNC stringlist *insert_sourcefile(char *string)
   372 {
   373   return insert_string(&sourcefiles,string);
   374 }
   375 
   376 SC_FUNC char *get_sourcefile(int index)
   377 {
   378   return get_string(&sourcefiles,index);
   379 }
   380 
   381 SC_FUNC void delete_sourcefiletable(void)
   382 {
   383   delete_stringtable(&sourcefiles);
   384   assert(sourcefiles.next==NULL);
   385 }
   386 
   387 
   388 /* ----- documentation tags -------------------------------------- */
   389 #if !defined SC_LIGHT
   390 static stringlist docstrings = {NULL, NULL};
   391 
   392 SC_FUNC stringlist *insert_docstring(char *string)
   393 {
   394   return insert_string(&docstrings,string);
   395 }
   396 
   397 SC_FUNC char *get_docstring(int index)
   398 {
   399   return get_string(&docstrings,index);
   400 }
   401 
   402 SC_FUNC void delete_docstring(int index)
   403 {
   404   delete_string(&docstrings,index);
   405 }
   406 
   407 SC_FUNC void delete_docstringtable(void)
   408 {
   409   delete_stringtable(&docstrings);
   410   assert(docstrings.next==NULL);
   411 }
   412 #endif /* !defined SC_LIGHT */
   413 
   414 
   415 /* ----- autolisting --------------------------------------------- */
   416 static stringlist autolist = {NULL, NULL};
   417 
   418 SC_FUNC stringlist *insert_autolist(char *string)
   419 {
   420   return insert_string(&autolist,string);
   421 }
   422 
   423 SC_FUNC char *get_autolist(int index)
   424 {
   425   return get_string(&autolist,index);
   426 }
   427 
   428 SC_FUNC void delete_autolisttable(void)
   429 {
   430   delete_stringtable(&autolist);
   431   assert(autolist.next==NULL);
   432 }
   433 
   434 
   435 /* ----- debug information --------------------------------------- */
   436 
   437 /* These macros are adapted from LibDGG libdgg-int64.h, see
   438  * http://www.dennougedougakkai-ndd.org/pub/libdgg/
   439  */
   440 #if defined(__STDC_VERSION__) && __STDC_VERSION__>=199901L
   441   #define __STDC_FORMAT_MACROS
   442   #define __STDC_CONSTANT_MACROS
   443   #include <inttypes.h>         /* automatically includes stdint.h */
   444 #elif (defined _MSC_VER || defined __BORLANDC__) && (defined _I64_MAX || defined HAVE_I64)
   445   #define PRId64 "I64d"
   446   #define PRIx64 "I64x"
   447 #else
   448   #define PRId64 "lld"
   449   #define PRIx64 "llx"
   450 #endif
   451 #if PAWN_CELL_SIZE==64
   452   #define PRIdC  PRId64
   453   #define PRIxC  PRIx64
   454 #elif PAWN_CELL_SIZE==32
   455   #define PRIdC  "ld"
   456   #define PRIxC  "lx"
   457 #else
   458   #define PRIdC  "d"
   459   #define PRIxC  "x"
   460 #endif
   461 
   462 static stringlist dbgstrings = {NULL, NULL};
   463 
   464 SC_FUNC stringlist *insert_dbgfile(const char *filename)
   465 {
   466 
   467   if (sc_status==statWRITE && (sc_debug & sSYMBOLIC)!=0) {
   468     char string[_MAX_PATH+40];
   469     assert(filename!=NULL);
   470     assert(strlen(filename)+40<sizeof string);
   471     sprintf(string,"F:%" PRIxC " %s",code_idx,filename);
   472     return insert_string(&dbgstrings,string);
   473   } /* if */
   474   return NULL;
   475 }
   476 
   477 SC_FUNC stringlist *insert_dbgline(int linenr)
   478 {
   479   if (sc_status==statWRITE && (sc_debug & sSYMBOLIC)!=0) {
   480     char string[40];
   481     if (linenr>0)
   482       linenr--;         /* line numbers are zero-based in the debug information */
   483     sprintf(string,"L:%" PRIxC " %x",code_idx,linenr);
   484     return insert_string(&dbgstrings,string);
   485   } /* if */
   486   return NULL;
   487 }
   488 
   489 SC_FUNC stringlist *insert_dbgsymbol(symbol *sym)
   490 {
   491   if (sc_status==statWRITE && (sc_debug & sSYMBOLIC)!=0) {
   492     char string[2*sNAMEMAX+128];
   493     char symname[2*sNAMEMAX+16];
   494 
   495     funcdisplayname(symname,sym->name);
   496     /* address tag:name codestart codeend ident vclass [tag:dim ...] */
   497     if (sym->ident==iFUNCTN) {
   498       sprintf(string,"S:%" PRIxC " %x:%s %" PRIxC " %" PRIxC " %x %x",
   499               sym->addr,sym->tag,symname,sym->addr,sym->codeaddr,sym->ident,sym->vclass);
   500     } else {
   501       sprintf(string,"S:%" PRIxC " %x:%s %" PRIxC " %" PRIxC " %x %x",
   502               sym->addr,sym->tag,symname,sym->codeaddr,code_idx,sym->ident,sym->vclass);
   503     } /* if */
   504     if (sym->ident==iARRAY || sym->ident==iREFARRAY) {
   505       #if !defined NDEBUG
   506         int count=sym->dim.array.level;
   507       #endif
   508       symbol *sub;
   509       strcat(string," [ ");
   510       for (sub=sym; sub!=NULL; sub=finddepend(sub)) {
   511         assert(sub->dim.array.level==count--);
   512         sprintf(string+strlen(string),"%x:%x ",sub->x.tags.index,sub->dim.array.length);
   513       } /* for */
   514       strcat(string,"]");
   515     } /* if */
   516 
   517     return insert_string(&dbgstrings,string);
   518   } /* if */
   519   return NULL;
   520 }
   521 
   522 SC_FUNC char *get_dbgstring(int index)
   523 {
   524   return get_string(&dbgstrings,index);
   525 }
   526 
   527 SC_FUNC void delete_dbgstringtable(void)
   528 {
   529   delete_stringtable(&dbgstrings);
   530   assert(dbgstrings.next==NULL);
   531 }