home *** CD-ROM | disk | FTP | other *** search
/ Amiga Elysian Archive / AmigaElysianArchive.iso / prog / c / cpp.lha / defmacio.c < prev    next >
C/C++ Source or Header  |  1991-04-15  |  12KB  |  483 lines

  1. /*
  2.  
  3.  
  4.  Copyright (C) 1990 Texas Instruments Incorporated.
  5.  
  6.  Permission is granted to any individual or institution to use, copy, modify,
  7.  and distribute this software, provided that this complete copyright and
  8.  permission notice is maintained, intact, in all copies and supporting
  9.  documentation.
  10.  
  11.  Texas Instruments Incorporated provides this software "as is" without
  12.  express or implied warranty.
  13.  
  14.  
  15.  *  
  16.  * Utility functions used by defmacros.
  17.  *
  18.  * Edit history
  19.  * Created: LGO 30-Mar-89 -- Initial design and implementation.
  20.  *
  21.  */
  22.  
  23. #include "defmacio.h"
  24.  
  25. /*
  26.  * Put a string in the input buffer used by getchar
  27.  * This lets us use scan_next for arbitrary strings.
  28.  */
  29. void set_inbuffer(instring)
  30.     char* instring;
  31. {
  32.   static FILEINFO inbuf = {0, 0, 0, 0, 0, 0, 0, 0};
  33.   inbuf.bptr = inbuf.buffer = instring;
  34.   MacInFile = &inbuf;
  35. }
  36.  
  37. /*
  38. // Skip whitespace characters and comments, returning the next character
  39. */
  40. char
  41. skip_blanks()
  42. {
  43.   register char c;
  44.  again:
  45.   while ((c = getchar()) != EOF && isspace(c));
  46.   if (c == '/') {
  47.     char nc = getchar();
  48.     if (nc == '/') {        /* If // comment, skip to end of line */
  49.       while ((c = getchar()) != EOF && c != '\n');
  50.       goto again;
  51.     } else if (nc == '*') {    /* If / * comment, skip to */
  52.       char p = getchar();
  53.       while ((c = getchar()) != EOF) {
  54.     if (c == '/' && p == '*') break;
  55.     p = c;
  56.       }
  57.       goto again;
  58.     } else            /* Else putback character after / */
  59.       unget();
  60.   } else if (c == '\\') {
  61.     char nc = getchar();
  62.     if (nc == '\n') goto again;          /* If \\\n, ignore */
  63.     unget();
  64.   }
  65.   return(c);
  66. }
  67.  
  68. /*
  69.  * Skip to next newline
  70.  */
  71. char
  72. skip_line()
  73. {
  74.   char c;
  75.   while ((c = getchar()) != EOF)
  76.     if (c == '\n') break;
  77.   return(c);
  78. }
  79.  
  80. /*
  81.  * Copy the next alphanumeric token
  82.  * the argument, str is a pointer to a string where the token is to be copied.
  83.  * Returns a pointer to the END of the token, which contains the NEXT character.
  84.  */
  85. char*
  86. copytoken(str)
  87.   char* str;
  88. {
  89.   int is_bad = TRUE;
  90.   char c = skip_blanks();
  91.   while (isalnum(c) ||
  92.      (c == '$') ||
  93.      (c == '_')) {
  94.     *str++ = c;
  95.     c = getchar();
  96.     is_bad = FALSE;
  97.   }
  98.   if(is_bad) {
  99.     if (c == EOF)
  100.       fprintf(stderr, "End of file while scanning for token\n");
  101.     else
  102.       fprintf(stderr, "Illegal character in token: '%c'\n", c);
  103.     return NULL;
  104.   }
  105.   unget();
  106.   *str = EOS;
  107.   return(str);
  108. }
  109.  
  110. STRING work_string = NULL;
  111.  
  112. static char*
  113. scan_next_string(delim)
  114.   char delim;                     /* Current delimiter */
  115. {
  116.   char c;                     /* Current character */
  117.   char p;                /* Previous character */
  118.   char* workp = work_string->buffp;    /* result buffer */
  119.   char* workend = work_string->buffend; /* end of result buffer */
  120.  
  121.   for (p = EOS; (c = getchar()) != EOF; p = c) {
  122.     if (workp >= workend-1) {
  123.       work_string->buffp = workp;
  124.       grow_STRING(work_string, 0);
  125.       workp = work_string->buffp;
  126.       workend = work_string->buffend;
  127.     }
  128.     *workp++ = c;
  129.     if (delim == c &&            /* Quit when delimeter found */
  130.     p != '\\' &&            /* and it's not quoted */
  131.     (delim != '/' || p == '*')) {     /* Special test for end of comment */
  132.       *workp = EOS;
  133.       work_string->buffp = workp;
  134.       return workp;
  135.     }
  136.   }
  137.   /* end of file when we get here */
  138.   *workp = EOS;
  139.   work_string->buffp = workp;
  140.   return workp;
  141. }
  142.  
  143.  
  144. char*
  145. scan_next_internal(delim, is_top_level)
  146.   char delim;                     /* Current delimiter */
  147.   int is_top_level;            /* flag */
  148. {
  149.   char newdelim;            /* New delimiter to look for */
  150.   int is_string = FALSE;        /* New is_string flag */
  151.   register char c;            /* Current character */
  152.   register char* workp = work_string->buffp;     /* result buffer */
  153.   register char* workend = work_string->buffend; /* end of result buffer */
  154.  
  155.   while ((c = getchar()) != EOF) {
  156.     if (workp >= workend-1) {
  157.       work_string->buffp = workp;
  158.       grow_STRING(work_string, 0);
  159.       workp = work_string->buffp;
  160.       workend = work_string->buffend;
  161.     }
  162.     *workp++ = c;
  163.     if (delim == c) {            /* Quit when delimeter found */
  164.       *workp = EOS;
  165.       work_string->buffp = workp;
  166.       return workp;
  167.     }
  168.     switch (c) {           /* Look for new delimeters when not is_string */
  169.     case '{':  newdelim = '}'; break;
  170.     case '[':  newdelim = ']'; break;
  171.     case '(':  newdelim = ')'; break;
  172.     case '<':
  173.       if (delim != '>')
  174.     continue;
  175.       newdelim = '>'; break;
  176.     case '\'':  newdelim = '\''; is_string = TRUE; break;
  177.     case '\"':  newdelim = '\"'; is_string = TRUE; break;
  178.     case '/':                  /* start of comment? */
  179.       c = getchar();
  180.       unget();
  181.       if (c == '/') {              /* standard comment */
  182.     newdelim = '\n';
  183.     is_string = TRUE;
  184.     break;
  185.       } else if (c == '*') {          /* c++ comment */
  186.     newdelim = '/';
  187.     is_string = TRUE;
  188.     break;
  189.       }
  190.       continue;
  191.     default:                  /* comma grabs args */
  192.       continue;
  193.     }                      /* end switch */
  194.     if (is_top_level && newdelim == delim) {
  195.       is_top_level = FALSE;
  196.       continue;        /* at top_level, with left side of delimiter */
  197.     }
  198.     work_string->buffp = workp;
  199.     if (is_string)
  200.       workp = scan_next_string(newdelim);
  201.     else
  202.       workp = scan_next_internal(newdelim, FALSE);
  203.     workend = work_string->buffend;
  204.     is_string = FALSE;
  205.   } /* end while */
  206.   /* end of file when we get here */
  207.   *workp = EOS;
  208.   work_string->buffp = workp;
  209.   return workp;
  210.  
  211. void scan_start() {
  212.   if(work_string == NULL)          /* Setup buffer */
  213.     work_string = make_STRING(4096);
  214.   work_string->buffp = work_string->buff;
  215. }
  216.  
  217. /*
  218.  * Get the next token, stopping at delim
  219.  */
  220. char* scan_next(delim)
  221.   char delim;                  /* delimiter */
  222. {
  223.   scan_start();
  224.   skip_blanks();            /* skip leading whitespace */
  225.   unget();
  226.   if (delim == ' ') {              /* ' ' means grab token */
  227.     work_string->buffp = copytoken(work_string->buffp);
  228.     if ((delim = getchar()) != '<') {      /* Grab <...> */
  229.       unget();
  230.     } else {
  231.       *work_string->buffp++ = delim;
  232.       scan_next_internal('>', FALSE);
  233.     }
  234.   } else {
  235.     scan_next_internal(delim, TRUE);
  236.   }
  237.   work_string->buffp++;
  238.   return work_string->buff;
  239. }
  240. /*
  241.  * Get the next token, stopping at delim
  242.  * Call scan_start before using this function
  243.  * The string returned is inside work_string, and
  244.  * will be clobbered on the next call to scan_start.
  245.  */
  246. char* scan_list(delim)
  247.   char delim;                  /* delimiter */
  248. {
  249.   unsigned int start = work_string->buffp - work_string->buff;
  250.   skip_blanks();            /* skip leading whitespace */
  251.   unget();
  252.   if (delim == ' ') {              /* ' ' means grab token */
  253.     if (work_string->buffend - work_string->buffp <= 128)
  254.       grow_STRING(work_string, 128);      /* Ensure at least 128 chars */
  255.     work_string->buffp = copytoken(work_string->buffp);
  256.   }
  257.   else
  258.     scan_next_internal(delim, TRUE);
  259.   work_string->buffp++;
  260.   return (work_string->buff+start);
  261. }
  262.  
  263. char*
  264. scan_token(delims)
  265.   char* delims;                  /* delimiters */
  266. {
  267.   register char* workp;
  268.   char* work;
  269.   register char c;
  270.   if(work_string == NULL)          /* Setup buffer */
  271.     work_string = make_STRING(3000);
  272.   workp = work_string->buff;
  273.   c = skip_blanks();            /* skip leading whitespace */
  274.   while(c != EOF) {
  275.     register char* p;
  276.     for(p=delims; *p!=EOS; p++)
  277.       if (*p == c) goto done;
  278.     *workp++ = c;
  279.     if (ispunct(c))            /* If {([<'" Use scan_next_internal */
  280.       for(p="{}()[]<>\'\'\"\""; *p!=EOS; p++)
  281.     if (*p++ == c) {
  282.       work_string->buffp = workp;
  283.       if (*p == '\'' || *p == '\"')
  284.         workp = scan_next_string(*p);
  285.       else
  286.         workp = scan_next_internal(*p, FALSE);
  287.       break;
  288.     }
  289.     c = getchar();
  290.   }
  291.  done:
  292.   unget();
  293.   work = work_string->buff;
  294.   while(workp>work && isspace(*(workp-1))) workp--;
  295.   *workp = EOS;                  /* trim trailing blanks */
  296.   return savestring(work);
  297. }
  298.  
  299. void
  300. put_string(string)
  301.   char* string;
  302. {
  303.   char c;
  304.   putchar('\"');
  305.   while ((c=*string++) != EOS)
  306.     switch (c) {
  307.       case '\"': putchar('\\');
  308.       default:  putchar(c);
  309.     }
  310.   putchar('\"');
  311. }
  312.  
  313. /* c_upcase -- Convert all alphabetical characters to uppercase
  314.  * Input:      Character string 
  315.  * Output:     Updated string
  316.  */
  317. char*
  318. c_upcase (s)
  319.   char* s;
  320. {
  321.   char* p = s;            /* Point to beginning of string */
  322.   while (*p != EOS) {        /* While there are still valid characters */
  323.     if (islower (*p))        /* if this is lower case */
  324.       *p = toupper (*p);    /* convert to uppercase */
  325.     p++;            /* Advance pointer */
  326.   }
  327.   return s;            /* Return reference to modified string */
  328. }
  329.  
  330.  
  331. /* c_downcase -- Convert all alphabetical characters to lowercase
  332.  * Input:        Character string
  333.  * Output:       Updated string
  334.  */
  335.  
  336. char*
  337. c_downcase (s)
  338.   char* s;
  339. {
  340.   char* p = s;            /* Point to beginning of string */
  341.   while (*p != EOS) {        /* While there are still valid characters */
  342.     if (isupper (*p))        /* if this is upper case */
  343.       *p = tolower (*p);    /* convert to lowercase  */
  344.     p++;            /* Advance pointer */
  345.   }
  346.   return s;            /* Return reference to modified string */
  347. }
  348.  
  349. /* c_capitalize -- Capitalize all words in a string. A word is defined as
  350.  *                 a sequence of characters separated by white space
  351.  * Input:          Character string
  352.  * Output:         Updated string
  353.  */
  354.  
  355. char*
  356. c_capitalize (s)
  357.   char* s;
  358. {
  359.   char* p = s;                /* Point to beginning of string */
  360.   while (TRUE) {            /* Infinite loop */
  361.     for ( ; *p && isspace(*p); p++);    /* Skip white space */
  362.     if (*p == EOS)                 /* If end of string */
  363.       return s;                /* Return string */
  364.     if (islower (*p))            /* If lower case */
  365.       *p = toupper (*p);        /* Convert character */
  366.     for ( ; *p && !isspace (*p); p++);    /* Search for white space */
  367.   }
  368. }
  369.  
  370. /*
  371.  * c_trim_all -- Removes any occurrence of the character(s) in "c" from "s"
  372.  * Input:    Source string and token string
  373.  * Output:   Modified string "s"
  374.  */
  375. char* c_trim_all (s, c)
  376.   char* s;
  377.   char* c;
  378. {
  379.   char* t0;
  380.   int old_length = strlen (s);          /* Old string "s" length */
  381.   int new_length = 0;              /* Counts characters in result */
  382.   char* p = getmem(old_length+1);      /* Temporary holding array */
  383.   int i;
  384.   for (i = 0; i < old_length; i++) {  /* For each character in string */
  385.     for (t0 = c; *t0 && s[i] != *t0; t0++); /* Scan for match */
  386.     if (*t0 == EOS)              /* If no match found */
  387.       p[new_length++] = s[i];          /* Copy character */
  388.   }
  389.   p[new_length] = EOS;              /* NULL terminate string */
  390.   strcpy (s, p);              /* Copy new string */
  391.   free(p);                  /* Deallocate temporary memory */
  392.   return s;                  /* Return pointer to new string */
  393. }
  394.  
  395. /*
  396.  * Primitive dynamic string support
  397.  */
  398.  
  399. STRING make_STRING(size)
  400.   int size;
  401. { STRING result = (STRING) getmem(sizeof(struct buf_string));
  402.   char* buff = getmem(size);
  403.   *buff = EOS;
  404.   result->buff = buff;
  405.   result->buffp = buff;
  406.   result->buffend = buff+size;
  407.   return result;
  408. }
  409.  
  410. void destroy_STRING(string)
  411.   STRING string;
  412. {
  413.   free(string->buff);
  414.   free(string);
  415. }
  416.  
  417. void grow_STRING(string, len)
  418.   STRING string;
  419.   unsigned int len;
  420. {
  421.   extern char* realloc(/* char*, int */);
  422.   char* old = string->buff;
  423.   unsigned int size = len + ((string->buffend - old) * 2);
  424.   char* new;
  425.   new = realloc(old, size);
  426.   if (new == NULL) cfatal("Heap exausted while growing string", "");
  427.   string->buffp = new + (string->buffp - old);
  428.   string->buff = new;
  429.   string->buffend = new + size;
  430. }
  431.  
  432. void append_STRING(string, chars)
  433.   STRING string;
  434.   char* chars;
  435. {  unsigned int len = strlen(chars);
  436.    if (string->buffend - string->buffp <= len)
  437.      grow_STRING(string, len);
  438.    strcpy(string->buffp, chars);
  439.    string->buffp += len;
  440. }
  441.  
  442. /*
  443. // Copy whitespace and comments into a string, returning the next character
  444. */
  445. char
  446. append_blanks(string)
  447.   STRING string;
  448. {
  449.   register char c;
  450.  again:
  451.   while ((c = getchar()) != EOF && isspace(c))
  452.     append_char(string, c);
  453.   if (c == '/') {
  454.     char nc = getchar();
  455.     if (nc == '/') {        /* If // comment, skip to end of line */
  456.       append_STRING(string, "//");
  457.       while ((c = getchar()) != EOF) {
  458.     append_char(string, c);
  459.     if (c == '\n') break;
  460.       }
  461.       goto again;
  462.     } else if (nc == '*') {    /* If / * comment, skip to */
  463.       char p = getchar();
  464.       append_STRING(string, "/*");
  465.       append_char(string, p);
  466.       while ((c = getchar()) != EOF) {
  467.     append_char(string, c);
  468.     if (c == '/' && p == '*') break;
  469.     p = c;
  470.       }
  471.       goto again;
  472.     } else            /* Else putback character after / */
  473.       unget();
  474.   } else if (c == '\\') {
  475.     char nc = getchar();
  476.     if (nc == '\n') goto again;          /* If \\\n, ignore */
  477.     unget();
  478.   }
  479.   *(string->buffp) = EOS;
  480.   return(c);
  481. }
  482.