home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume4 / shortc < prev    next >
Internet Message Format  |  1986-11-30  |  7KB

  1. From: jim@ism780.UUCP
  2. Subject: shortc: C program to map flexnames into short identifiers
  3. Newsgroups: mod.sources
  4. Approved: jpn@panda.UUCP
  5.  
  6. Mod.sources:  Volume 4, Issue 13
  7. Submitted by: sources@panda
  8.  
  9. [   This is a repost of an article that was on net.sources in 1983.  I
  10.     mentioned that I had saved a copy of this - and the response has been
  11.     overwhelming.  So here it is:  enjoy!
  12.  
  13.     John P. Nelson, Moderator, mod.sources
  14.     (decvax!genrad!panda!jpn  seismo!harvard!talcott!panda!jpn)
  15. ]
  16.  
  17.  
  18. From: jim@ism780.UUCP
  19. Newsgroups: net.sources
  20. Subject: shortc: C program to map flexnames into short identifiers
  21. Date: Sun, 11-Dec-83 23:04:00 EST
  22.  
  23. char ID[] = "@(#) shortc";
  24. char Usage[] = "usage: shortc [-symlen] [-p] file ... > Short.h\n";
  25. /*
  26.    Produce a set of preprocessor defines which guarantee that all identifiers
  27.    in the files are unique in the first symlen (default 7) characters.
  28.    Include the output into each file (or into a common header file).
  29.    Since the symbols being redefined are ambiguous within symlen chars
  30.    (that was the problem in the first place), the files must be compiled
  31.    using a flexnames version of cpp.
  32.    Lacking that, turn the output into a sed script and massage the source
  33.    files.  In this case, you may need to specify -p to parse preprocessor
  34.    lines, but watch for things like include-file names.
  35.    If using cpp, preprocessor symbols should be weeded out by hand; otherwise
  36.    they will cause (innocuous) redefinition messages.
  37.  */
  38.  
  39. #include <ctype.h>
  40. #include <stdio.h>
  41.  
  42. #define SYMLEN  7           /* symbols must be unique within ... chars */
  43. #define MAXLEN  128         /* need a limit for tokenizing */
  44. #define HASHSIZ 2048        /* power of 2; not an upper limit */
  45.  
  46. typedef struct Symbol symbol;
  47. struct Symbol {
  48.     symbol  *link;          /* hash chain */
  49.     union {
  50.         char   *xprefix;   /* prefix for mapped name if flag > SEEN */
  51.         symbol *xtrunc;    /* symbol which truncates to this one
  52.                   if flag == TRUNC */
  53.     } x;
  54.     char    flag;
  55.     char    inname[1];
  56. };
  57. #define prefix  x.xprefix
  58. #define trunc   x.xtrunc
  59. #define NOTSEEN 0           /* symbol never seen */
  60. #define TRUNC   1           /* trunc points to symbol which truncates to
  61.                    this one */
  62. #define SEEN    2           /* there is no conflict with this symbol */
  63. /*              > SEEN */   /* prefix must be added to resolve conflict */
  64.  
  65. symbol  *symtab[HASHSIZ];
  66.  
  67. int     symlen  = SYMLEN;
  68. char    parsepp;            /* if set, parse preprocessor lines */
  69.  
  70. symbol  *lookup();
  71. char    *token(), *truncname();
  72. char    *myalloc();
  73.  
  74. extern  char *strcpy(), *strncpy();
  75. extern  char *malloc();
  76.  
  77. main (argc, argv) register char **argv; register argc; /*: entry point */
  78. {
  79.     while( --argc > 0 )
  80.         doarg(*++argv);
  81.  
  82.     dump();
  83.     exit(0);
  84. }
  85.  
  86. doarg (arg) char *arg; /*: process one file or flag arg */
  87. {
  88.     register char *s;
  89.     register symbol *y;
  90.  
  91.     if( *arg == '-' )
  92.     {   arg++;
  93.         if( isdigit(*arg) )
  94.         symlen = atoi(arg);
  95.         else if( *arg == 'p' )
  96.         parsepp = 1;
  97.         else fputs(Usage, stderr);
  98.         return;
  99.     }
  100.  
  101.     if( freopen(arg, "r", stdin) == NULL )
  102.     {   perror(arg);
  103.         return;
  104.     }
  105.  
  106.     while( s = token() )
  107.         if( (y = lookup(s))->flag < SEEN )
  108.         newname(y);
  109. }
  110.  
  111. newname (y) register symbol *y; /*: pick a new non-colliding name */
  112. {
  113.     register symbol *a;
  114.  
  115.     /* repeat until no collision */
  116.     for( ;; )
  117.     {   /* pick another name */
  118.         nextname(y);
  119.         /* check its truncation for conflicts */
  120.         a = lookup(truncname(y));
  121.         if( a->flag == NOTSEEN )
  122.         break;
  123.         /* if this is an original symbol and it collides with another
  124.          * (maybe modified) symbol, fix the other one instead of this one
  125.          */
  126.         if( a->flag == TRUNC && y->flag == SEEN )
  127.         {   newname(a->trunc);
  128.         break;
  129.         }
  130.         /* if already a short name, ok */
  131.         if( a == y )
  132.         return;
  133.     }
  134.     /* flag what this truncates to */
  135.     a->trunc = y;
  136.     a->flag = TRUNC;
  137. }
  138.  
  139. nextname (y) register symbol *y; /*: find next possible name for this symbol */
  140. {
  141.     register char *s, *p;
  142.     register n;
  143.  
  144.     switch( y->flag )
  145.     {   case TRUNC:
  146.         /* if another symbol truncates to this one, fix it not to */
  147.         newname(y->trunc);
  148.         case NOTSEEN:
  149.         /* this symbol's name is available, so use it */
  150.         y->flag = SEEN;
  151.         return;
  152.     }
  153.     /* prefix++ in base 26 */
  154.     for( n = y->flag-SEEN, p = y->prefix, s = p+n; s > p; *s = 'A' )
  155.         if( ++*--s <= 'Z' )     /* love that syntax */
  156.         return;
  157.  
  158.     /* overflow; need new digit */
  159.     y->prefix = s = myalloc(n+2);
  160.     *s++ = 'A';
  161.     if( y->flag++ == SEEN )
  162.         *s = '\0';
  163.     else
  164.     {   strcpy(s, p);
  165.         free(p);
  166.     }
  167. }
  168.  
  169. char *truncname (y) register symbol *y; /*: return symbol name truncated to symlen chars */
  170. {
  171.     static char buf[MAXLEN+10];
  172.  
  173.     register n = y->flag-SEEN;
  174.  
  175.     sprintf(buf, "%.*s%.*s", n, y->prefix, symlen-n, y->inname);
  176.     return buf;
  177. }
  178.  
  179. symbol *lookup(s) char *s; /*: find name in symbol table */
  180. {
  181.     register h;
  182.  
  183.     {   register char *p;
  184.         register c;
  185.  
  186.         for( h = 0, p = s; (c = *p++); )
  187.         h += h + c;
  188.     }
  189.  
  190.     {   register symbol *y, **yy;
  191.  
  192.         for( y = *(yy = &symtab[h & HASHSIZ-1]);; y = y->link )
  193.         {   if( !y )
  194.         {   y = (symbol *)myalloc(sizeof *y + strlen(s));
  195.             strcpy(y->inname, s);
  196.             y->flag = NOTSEEN;
  197.             y->link = *yy;
  198.             *yy = y;
  199.             break;
  200.         }
  201.         if( strcmp(y->inname, s) == 0 )
  202.             break;
  203.         }
  204.         return y;
  205.     }
  206. }
  207.  
  208. dump () /*: output all mappings */
  209. {
  210.     register symbol *y;
  211.     register n;
  212.  
  213.     for( n = HASHSIZ; --n >= 0; )
  214.         for( y = symtab[n]; y; y = y->link )
  215.         if( y->flag > SEEN )
  216.             printf("#define %s %s%s\n", y->inname,
  217.                         y->prefix, y->inname);
  218. }
  219.  
  220. char *token () /*: return next interesting identifier */
  221. {
  222.     register c, state = 0;
  223.     register char *p;
  224.     static char buf[MAXLEN+1];
  225.  
  226.     for( p = buf; (c = getchar()) != EOF; )
  227.     {   if( state )
  228.         switch( state )
  229.         {   case '/':
  230.             if( c != '*' )
  231.             {   state = 0;
  232.             break;
  233.             }
  234.             state = c;
  235.             continue;
  236.  
  237.         case 'S':
  238.             if( c == '/' )
  239.             state = 0;
  240.             else
  241.             state = '*';
  242.         case '*':
  243.             if( c == state )
  244.             state = 'S';
  245.             continue;
  246.  
  247.         default:
  248.             if( c == '\\' )
  249.             (void) getchar();
  250.             else if( c == state )
  251.             state = 0;
  252.             continue;
  253.         }
  254.         if( isalnum(c) || c == '_' )
  255.         {   if( p < &buf[sizeof buf - 1] )
  256.             *p++ = c;
  257.         continue;
  258.         }
  259.         if( p > buf )
  260.         {   if( p-buf >= symlen && !isdigit(*buf) )
  261.         {   *p = '\0';
  262.             ungetc(c, stdin);
  263.             return buf;
  264.         }
  265.         p = buf;
  266.         }
  267.         if( c == '"' || c == '\'' || c == '/' )
  268.         state = c;
  269.         else if( c == '#' && !parsepp )
  270.         state = '\n';
  271.     }
  272.     return NULL;
  273. }
  274.  
  275. char *myalloc(n) /*: malloc with error detection */
  276. {
  277.     register char *p;
  278.  
  279.     if( !(p = malloc((unsigned)n)) )
  280.     {   fprintf(stderr, "Out of space\n");
  281.         exit(1);
  282.     }
  283.     return p;
  284. }
  285.  
  286. --------
  287.  
  288.  
  289.