home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 35 Internet / 35-Internet.zip / nuweb087.zip / names.c < prev    next >
C/C++ Source or Header  |  1996-02-28  |  11KB  |  369 lines

  1. #include "global.h"
  2. enum { LESS, GREATER, EQUAL, PREFIX, EXTENSION };
  3.  
  4. static int compare(x, y)
  5.      char *x;
  6.      char *y;
  7. {
  8.   int len, result;
  9.   int xl = strlen(x);
  10.   int yl = strlen(y);
  11.   int xp = x[xl - 1] == ' ';
  12.   int yp = y[yl - 1] == ' ';
  13.   if (xp) xl--;
  14.   if (yp) yl--;
  15.   len = xl < yl ? xl : yl;
  16.   result = strncmp(x, y, len);
  17.   if (result < 0) return GREATER;
  18.   else if (result > 0) return LESS;
  19.   else if (xl < yl) {
  20.     if (xp) return EXTENSION;
  21.     else return LESS;
  22.   }
  23.   else if (xl > yl) {
  24.     if (yp) return PREFIX;
  25.     else return GREATER;
  26.   }
  27.   else return EQUAL;
  28. }
  29. char *save_string(s)
  30.      char *s;
  31. {
  32.   char *new = (char *) arena_getmem((strlen(s) + 1) * sizeof(char));
  33.   strcpy(new, s);
  34.   return new;
  35. }
  36. static int ambiguous_prefix();
  37.  
  38. Name *prefix_add(root, spelling)
  39.      Name **root;
  40.      char *spelling;
  41. {
  42.   Name *node = *root;
  43.   while (node) {
  44.     switch (compare(node->spelling, spelling)) {
  45.     case GREATER:   root = &node->rlink;
  46.                     break;
  47.     case LESS:      root = &node->llink;
  48.                     break;
  49.     case EQUAL:     return node;
  50.     case EXTENSION: node->spelling = save_string(spelling);
  51.                     return node;
  52.     case PREFIX:    {
  53.                       if (ambiguous_prefix(node->llink, spelling) ||
  54.                           ambiguous_prefix(node->rlink, spelling))
  55.                         fprintf(stderr,
  56.                                 "%s: ambiguous prefix @<%s...@> (%s, line %d)\n",
  57.                                 command_name, spelling, source_name, source_line);
  58.                     }
  59.                     return node;
  60.     }
  61.     node = *root;
  62.   }
  63.   {
  64.     node = (Name *) arena_getmem(sizeof(Name));
  65.     node->spelling = save_string(spelling);
  66.     node->mark = FALSE;
  67.     node->llink = NULL;
  68.     node->rlink = NULL;
  69.     node->uses = NULL;
  70.     node->defs = NULL;
  71.     node->tab_flag = TRUE;
  72.     node->indent_flag = TRUE;
  73.     node->debug_flag = FALSE;
  74.     *root = node;
  75.     return node;
  76.   }
  77. }
  78. static int ambiguous_prefix(node, spelling)
  79.      Name *node;
  80.      char *spelling;
  81. {
  82.   while (node) {
  83.     switch (compare(node->spelling, spelling)) {
  84.     case GREATER:   node = node->rlink;
  85.                     break;
  86.     case LESS:      node = node->llink;
  87.                     break;
  88.     case EQUAL:
  89.     case EXTENSION:
  90.     case PREFIX:    return TRUE;
  91.     }
  92.   }
  93.   return FALSE;
  94. }
  95. static int robs_strcmp(x, y)
  96.      char *x;
  97.      char *y;
  98. {
  99.   char *xx = x;
  100.   char *yy = y;
  101.   int xc = toupper(*xx);
  102.   int yc = toupper(*yy);
  103.   while (xc == yc && xc) {
  104.     xx++;
  105.     yy++;
  106.     xc = toupper(*xx);
  107.     yc = toupper(*yy);
  108.   }
  109.   if (xc != yc) return xc - yc;
  110.   xc = *x;
  111.   yc = *y;
  112.   while (xc == yc && xc) {
  113.     x++;
  114.     y++;
  115.     xc = *x;
  116.     yc = *y;
  117.   }
  118.   if (isupper(xc) && islower(yc))
  119.     return xc * 2 - (toupper(yc) * 2 + 1);
  120.   if (islower(xc) && isupper(yc))
  121.     return toupper(xc) * 2 + 1 - yc * 2;
  122.   return xc - yc;
  123. }
  124. Name *name_add(root, spelling)
  125.      Name **root;
  126.      char *spelling;
  127. {
  128.   Name *node = *root;
  129.   while (node) {
  130.     int result = robs_strcmp(node->spelling, spelling);
  131.     if (result > 0)
  132.       root = &node->llink;
  133.     else if (result < 0)
  134.       root = &node->rlink;
  135.     else
  136.       return node;
  137.     node = *root;
  138.   }
  139.   {
  140.     node = (Name *) arena_getmem(sizeof(Name));
  141.     node->spelling = save_string(spelling);
  142.     node->mark = FALSE;
  143.     node->llink = NULL;
  144.     node->rlink = NULL;
  145.     node->uses = NULL;
  146.     node->defs = NULL;
  147.     node->tab_flag = TRUE;
  148.     node->indent_flag = TRUE;
  149.     node->debug_flag = FALSE;
  150.     *root = node;
  151.     return node;
  152.   }
  153. }
  154. Name *collect_file_name()
  155. {
  156.   Name *new_name;
  157.   char name[100];
  158.   char *p = name;
  159.   int start_line = source_line;
  160.   int c = source_get();
  161.   while (isspace(c))
  162.     c = source_get();
  163.   while (isgraph(c)) {
  164.     *p++ = c;
  165.     c = source_get();
  166.   }
  167.   if (p == name) {
  168.     fprintf(stderr, "%s: expected file name (%s, %d)\n",
  169.             command_name, source_name, start_line);
  170.     exit(-1);
  171.   }
  172.   *p = '\0';
  173.   new_name = name_add(&file_names, name);
  174.   {
  175.     while (1) {
  176.       while (isspace(c))
  177.         c = source_get();
  178.       if (c == '-') {
  179.         c = source_get();
  180.         do {
  181.           switch (c) {
  182.             case 't': new_name->tab_flag = FALSE;
  183.                       break;
  184.             case 'd': new_name->debug_flag = TRUE;
  185.                       break;
  186.             case 'i': new_name->indent_flag = FALSE;
  187.                       break;
  188.             default : fprintf(stderr, "%s: unexpected per-file flag (%s, %d)\n",
  189.                               command_name, source_name, source_line);
  190.                       break;
  191.           }
  192.           c = source_get();
  193.         } while (!isspace(c));
  194.       }
  195.       else break;
  196.     }
  197.   }
  198.   if (c != '@' || source_get() != '{') {
  199.     fprintf(stderr, "%s: expected @{ after file name (%s, %d)\n",
  200.             command_name, source_name, start_line);
  201.     exit(-1);
  202.   }
  203.   return new_name;
  204. }
  205. Name *collect_macro_name()
  206. {
  207.   char name[100];
  208.   char *p = name;
  209.   int start_line = source_line;
  210.   int c = source_get();
  211.   while (isspace(c))
  212.     c = source_get();
  213.   while (c != EOF) {
  214.     switch (c) {
  215.       case '@':  {
  216.                    c = source_get();
  217.                    switch (c) {
  218.                      case '@': *p++ = c;
  219.                                break;
  220.                      case '{': {
  221.                                  if (p > name && p[-1] == ' ')
  222.                                    p--;
  223.                                  if (p - name > 3 && p[-1] == '.' && p[-2] == '.' && p[-3] == '.') {
  224.                                    p[-3] = ' ';
  225.                                    p -= 2;
  226.                                  }
  227.                                  if (p == name || name[0] == ' ') {
  228.                                    fprintf(stderr, "%s: empty scrap name (%s, %d)\n",
  229.                                            command_name, source_name, source_line);
  230.                                    exit(-1);
  231.                                  }
  232.                                  *p = '\0';
  233.                                  return prefix_add(¯o_names, name);
  234.                                }
  235.                      default:  fprintf(stderr,
  236.                                        "%s: unexpected @%c in macro name (%s, %d)\n",
  237.                                        command_name, c, source_name, start_line);
  238.                                exit(-1);
  239.                    }
  240.                  }
  241.                  break;
  242.       case '\t':
  243.       case ' ':  *p++ = ' ';
  244.                  do
  245.                    c = source_get();
  246.                  while (c == ' ' || c == '\t');
  247.                  break;
  248.       case '\n': {
  249.                    do
  250.                      c = source_get();
  251.                    while (isspace(c));
  252.                    if (c != '@' || source_get() != '{') {
  253.                      fprintf(stderr, "%s: expected @{ after macro name (%s, %d)\n",
  254.                              command_name, source_name, start_line);
  255.                      exit(-1);
  256.                    }
  257.                    {
  258.                      if (p > name && p[-1] == ' ')
  259.                        p--;
  260.                      if (p - name > 3 && p[-1] == '.' && p[-2] == '.' && p[-3] == '.') {
  261.                        p[-3] = ' ';
  262.                        p -= 2;
  263.                      }
  264.                      if (p == name || name[0] == ' ') {
  265.                        fprintf(stderr, "%s: empty scrap name (%s, %d)\n",
  266.                                command_name, source_name, source_line);
  267.                        exit(-1);
  268.                      }
  269.                      *p = '\0';
  270.                      return prefix_add(¯o_names, name);
  271.                    }
  272.                  }
  273.       default:   *p++ = c;
  274.                  c = source_get();
  275.                  break;
  276.     }
  277.   }
  278.   fprintf(stderr, "%s: expected macro name (%s, %d)\n",
  279.           command_name, source_name, start_line);
  280.   exit(-1);
  281.   return NULL;  /* unreachable return to avoid warnings on some compilers */
  282. }
  283. Name *collect_scrap_name()
  284. {
  285.   char name[100];
  286.   char *p = name;
  287.   int c = source_get();
  288.   while (c == ' ' || c == '\t')
  289.     c = source_get();
  290.   while (c != EOF) {
  291.     switch (c) {
  292.       case '@':  {
  293.                    c = source_get();
  294.                    switch (c) {
  295.                      case '@': *p++ = c;
  296.                                c = source_get();
  297.                                break;
  298.                      case '>': {
  299.                                  if (p > name && p[-1] == ' ')
  300.                                    p--;
  301.                                  if (p - name > 3 && p[-1] == '.' && p[-2] == '.' && p[-3] == '.') {
  302.                                    p[-3] = ' ';
  303.                                    p -= 2;
  304.                                  }
  305.                                  if (p == name || name[0] == ' ') {
  306.                                    fprintf(stderr, "%s: empty scrap name (%s, %d)\n",
  307.                                            command_name, source_name, source_line);
  308.                                    exit(-1);
  309.                                  }
  310.                                  *p = '\0';
  311.                                  return prefix_add(¯o_names, name);
  312.                                }
  313.                      default:  fprintf(stderr,
  314.                                        "%s: unexpected @%c in macro name (%s, %d)\n",
  315.                                        command_name, c, source_name, source_line);
  316.                                exit(-1);
  317.                    }
  318.                  }
  319.                  break;
  320.       case '\t':
  321.       case ' ':  *p++ = ' ';
  322.                  do
  323.                    c = source_get();
  324.                  while (c == ' ' || c == '\t');
  325.                  break;
  326.       default:   if (!isgraph(c)) {
  327.                    fprintf(stderr,
  328.                            "%s: unexpected character in macro name (%s, %d)\n",
  329.                            command_name, source_name, source_line);
  330.                    exit(-1);
  331.                  }
  332.                  *p++ = c;
  333.                  c = source_get();
  334.                  break;
  335.     }
  336.   }
  337.   fprintf(stderr, "%s: unexpected end of file (%s, %d)\n",
  338.           command_name, source_name, source_line);
  339.   exit(-1);
  340.   return NULL;  /* unreachable return to avoid warnings on some compilers */
  341. }
  342. static Scrap_Node *reverse();   /* a forward declaration */
  343.  
  344. void reverse_lists(names)
  345.      Name *names;
  346. {
  347.   while (names) {
  348.     reverse_lists(names->llink);
  349.     names->defs = reverse(names->defs);
  350.     names->uses = reverse(names->uses);
  351.     names = names->rlink;
  352.   }
  353. }
  354. static Scrap_Node *reverse(a)
  355.      Scrap_Node *a;
  356. {
  357.   if (a) {
  358.     Scrap_Node *b = a->next;
  359.     a->next = NULL;
  360.     while (b) {
  361.       Scrap_Node *c = b->next;
  362.       b->next = a;
  363.       a = b;
  364.       b = c;
  365.     }
  366.   }
  367.   return a;
  368. }
  369.