home *** CD-ROM | disk | FTP | other *** search
/ Chip 1998 February / CHIP_2_98.iso / misc / src / rpm / build / macro.c < prev    next >
C/C++ Source or Header  |  1997-09-17  |  6KB  |  307 lines

  1. /* macro.c - %macro handling */
  2. #include "miscfn.h"
  3.  
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <ctype.h>
  7. #include "macro.h"
  8.  
  9. #ifdef DEBUG
  10. #include <stdio.h>
  11. #define rpmError fprintf
  12. #define RPMERR_BADSPEC stderr
  13. static void dumpTable(void);
  14. #else
  15. #include "rpmlib.h"
  16. #endif
  17.  
  18. static void expandMacroTable(void);
  19. static int compareMacros(const void *ap, const void *bp);
  20. static struct macroEntry *findEntry(char *name);
  21. static int handleDefine(char *buf);
  22. static int parseMacro(char *p, char **macro, char **next);
  23.  
  24. /* This should be a hash table, but I doubt anyone will ever notice */
  25.  
  26. #define MACRO_CHUNK_SIZE 16
  27.  
  28. struct macroEntry {
  29.     char *name;
  30.     char *expansion;
  31. };
  32.  
  33. static struct macroEntry *macroTable = NULL;
  34. static int macrosAllocated = 0;
  35. static int firstFree = 0;
  36.  
  37. /*************************************************************************/
  38. /*                                                                       */
  39. /* Parsing routines                                                      */
  40. /*                                                                       */
  41. /*************************************************************************/
  42.  
  43. int expandMacros(char *buf)
  44. {
  45.     char bufA[1024];
  46.     char *copyTo, *copyFrom;
  47.     char *name, *rest, *first;
  48.     struct macroEntry *p;
  49.     
  50.     if (! buf) {
  51.     return 0;
  52.     }
  53.  
  54.     /* Check if commented out */
  55.     first = buf;
  56.     while (*first && isspace(*first)) {
  57.     first++;
  58.     }
  59.     if (*first == '#') {
  60.     return 0;
  61.     }
  62.     
  63.     copyFrom = buf;
  64.     copyTo = bufA;
  65.  
  66.     while (*copyFrom) {
  67.     if (*copyFrom != '%') {
  68.         *copyTo++ = *copyFrom++;
  69.     } else {
  70.         if (parseMacro(copyFrom+1, &name, &rest)) {
  71.         return 1;
  72.         }
  73.         if (!strcmp(name, "define")) {
  74.         if (handleDefine(rest)) {
  75.             return 1;
  76.         }
  77.         /* result is empty */
  78.         *buf = '\0';
  79.         return 0;
  80.         }
  81.         if (!strcmp(name, "%")) {
  82.         *copyTo++ = '%';
  83.         copyFrom = rest;
  84.         } else {
  85.         /* a real live macro! */
  86.         p = findEntry(name);
  87.         if (! p) {
  88.             /* undefined - just leave it */
  89.             *copyTo++ = '%';
  90.             copyFrom = name;
  91.         } else {
  92.             copyFrom = p->expansion;
  93.         }
  94.         while (*copyFrom) {
  95.             *copyTo++ = *copyFrom++;
  96.         }
  97.         copyFrom = rest;
  98.         }
  99.     }
  100.     }
  101.     *copyTo = '\0';
  102.     strcpy(buf, bufA);
  103.     return 0;
  104. }
  105.  
  106. static int parseMacro(char *p, char **macro, char **next)
  107. {
  108.     /* This static var is gross, but we can get away with it */
  109.     /* because the result is used immediately, even when we  */
  110.     /* are recursing.                                        */
  111.  
  112.     static char macroBuf[1024];
  113.     char save;
  114.     
  115.     /* Find end of macro, handling %{...} construct */
  116.  
  117.     if (! p) {
  118.     /* empty macro name */
  119.     rpmError(RPMERR_BADSPEC, "Empty macro name\n");
  120.     return 2;
  121.     }
  122.     
  123.     if (*p == '{') {
  124.     *next = strchr(p, '}');
  125.     if (! *next) {
  126.         /* unterminated */
  127.         rpmError(RPMERR_BADSPEC, "Unterminated {: %s\n", p);
  128.         return 1;
  129.     }
  130.     **next = '\0';
  131.     *macro = strtok(p+1, " \n\t");
  132.     if (! *macro) {
  133.         /* empty macro name */
  134.         rpmError(RPMERR_BADSPEC, "Empty macro name\n");
  135.         return 2;
  136.     }
  137.     (*next)++;
  138.     return 0;
  139.     }
  140.  
  141.     if (*p == '%') {
  142.     *next = p + 1;
  143.     *macro = "%";
  144.     return 0;
  145.     }
  146.  
  147.     if (isspace(*p) || ! *p) {
  148.     /* illegal % syntax */
  149.     rpmError(RPMERR_BADSPEC, "Illegal %% syntax: %s\n", p);
  150.     return 3;
  151.     }
  152.  
  153.     *next = *macro = p;
  154.     while (**next && (isalnum(**next) || **next == '_')) {
  155.     (*next)++;
  156.     }
  157.     if (! **next) {
  158.     return 0;
  159.     }
  160.     save = **next;
  161.     **next = '\0';
  162.     strcpy(macroBuf, *macro);
  163.     **next = save;
  164.     *macro = macroBuf;
  165.     return 0;
  166. }
  167.  
  168. static int handleDefine(char *buf)
  169. {
  170.     char *last, *name, *expansion;
  171.  
  172.     /* get the name */
  173.  
  174.     name = buf;
  175.     while (*name && isspace(*name)) {
  176.     name++;
  177.     }
  178.     if (! *name) {
  179.     /* missing macro name */
  180.     rpmError(RPMERR_BADSPEC, "Unfinished %%define\n");
  181.     return 1;
  182.     }
  183.     expansion = name;
  184.     while (*expansion && !isspace(*expansion)) {
  185.     expansion++;
  186.     }
  187.     if (*expansion) {
  188.     *expansion++ = '\0';
  189.     }
  190.     
  191.     /* get the expansion */
  192.     
  193.     while (*expansion && isspace(*expansion)) {
  194.     expansion++;
  195.     }
  196.     if (*expansion) {
  197.     /* strip blanks from end */
  198.     last = expansion + strlen(expansion) - 1;
  199.     while (isspace(*last)) {
  200.         *last-- = '\0';
  201.     }
  202.     }
  203.  
  204.     expandMacros(expansion);
  205.     addMacro(name, expansion);
  206.  
  207.     return 0;
  208. }
  209.  
  210. #ifdef DEBUG
  211. static void dumpTable()
  212. {
  213.     int i;
  214.     
  215.     for (i = 0; i < firstFree; i++) {
  216.     printf("%s->%s.\n", macroTable[i].name,
  217.            macroTable[i].expansion);
  218.     }
  219. }
  220.  
  221. void main(void)
  222. {
  223.     char buf[1024];
  224.     int x;
  225.  
  226.     while(gets(buf)) {
  227.     x = expandMacros(buf);
  228.     printf("%d->%s<-\n", x, buf);
  229.     }
  230. }
  231. #endif
  232.  
  233. /*************************************************************************/
  234. /*                                                                       */
  235. /* Table handling routines                                               */
  236. /*                                                                       */
  237. /*************************************************************************/
  238.  
  239. void resetMacros(void)
  240. {
  241.     int i;
  242.     
  243.     if (! macrosAllocated) {
  244.     expandMacroTable();
  245.     return;
  246.     }
  247.  
  248.     for (i = 0; i < firstFree; i++) {
  249.     free(macroTable[i].name);
  250.     free(macroTable[i].expansion);
  251.     }
  252.     firstFree = 0;
  253. }
  254.  
  255. void addMacro(char *name, char *expansion)
  256. {
  257.     struct macroEntry *p;
  258.  
  259.     p = findEntry(name);
  260.     if (p) {
  261.     free(p->expansion);
  262.     p->expansion = strdup(expansion);
  263.     return;
  264.     }
  265.     
  266.     if (firstFree == macrosAllocated) {
  267.     expandMacroTable();
  268.     }
  269.  
  270.     p = macroTable + firstFree++;
  271.     p->name = strdup(name);
  272.     p->expansion = strdup(expansion);
  273.  
  274.     qsort(macroTable, firstFree, sizeof(*macroTable), compareMacros);
  275. }
  276.  
  277. static struct macroEntry *findEntry(char *name)
  278. {
  279.     struct macroEntry key;
  280.  
  281.     if (! firstFree) {
  282.     return NULL;
  283.     }
  284.     
  285.     key.name = name;
  286.     return bsearch(&key, macroTable, firstFree,
  287.            sizeof(*macroTable), compareMacros);
  288. }
  289.  
  290. static int compareMacros(const void *ap, const void *bp)
  291. {
  292.     return strcmp(((struct macroEntry *)ap)->name,
  293.           ((struct macroEntry *)bp)->name);
  294. }
  295.  
  296. static void expandMacroTable()
  297. {
  298.     macrosAllocated += MACRO_CHUNK_SIZE;
  299.     if (! macrosAllocated) {
  300.     macroTable = malloc(sizeof(*macroTable) * macrosAllocated);
  301.     firstFree = 0;
  302.     } else {
  303.     macroTable = realloc(macroTable,
  304.                  sizeof(*macroTable) * macrosAllocated);
  305.     }
  306. }
  307.