📄 cccp.c
字号:
ip2->buf = xbuf; ip2->length = totlen; /* skip the input over the whole macro call. */ ip->bufp = bp; } else { ip2->buf = ip2->bufp = defn->expansion; ip2->length = defn->length; } rescan (ip2, op); --indepth; *excess_newlines_ptr += newlines_found; ip->lineno += newlines_found; return 0; nope: error ("argument mismatch"); --indepth; return 1;}/* * skip a balanced paren string up to the next comma. */U_CHAR *skip_macro_argument(bp, ip, newlines) U_CHAR *bp; FILE_BUF *ip; int *newlines;{ int paren = 0; int quotec = 0; while (bp < ip->buf + ip->length) { switch (*bp) { case '(': paren++; break; case ')': if (--paren < 0) return bp; break; case '\n': ++*newlines; break; case '/': if (bp[1] != '*' || bp + 1 >= ip->buf + ip->length) break; bp += 2; while ((bp[0] != '*' || bp[1] != '/') && bp + 1 < ip->buf + ip->length) { if (*bp == '\n') ++*newlines; bp++; } break; case '\'': /* JF handle quotes right */ case '\"': for (quotec = *bp++; bp < ip->buf + ip->length && *bp != quotec; bp++) { if (*bp == '\\') bp++; if (*bp == '\n') ++*newlines; } break; case ',': if (paren == 0) return bp; break; } bp++; } return bp;}/* * error - print out message. also make print on stderr. Uses stdout * now for debugging convenience. */error (msg) U_CHAR *msg;{ int i; FILE_BUF *ip = NULL; for (i = indepth - 1; i >= 0; i--) if (instack[i].fname != NULL) { ip = &instack[i]; break; } if (ip != NULL) fprintf(stdout, "file %s, offset %d (line %d): ", ip->fname, ip->bufp - ip->buf, ip->lineno); fprintf(stdout, "%s\n", msg); return 0;}/* * if OBUF doesn't have NEEDED bytes after OPTR, make it bigger * this should be a macro, for speed. * The "expand" in the name of this routine means buffer expansion, * not macro expansion. It may become necessary to have some hacky * mechanism for flushing out the output buffer if it gets too big. * * As things stand, nothing is ever placed in the output buffer to be * removed again except when it's KNOWN to be part of an identifier, * so flushing and moving down everything left, instead of expanding, * should work ok. */U_CHAR *check_expand(obuf, needed) register FILE_BUF *obuf; register int needed;{ register int i; register U_CHAR *p; if (obuf->length - (obuf->bufp - obuf->buf) > needed) return obuf->buf; i = 2 * obuf->length; if (needed >= i) i += (3 * needed) / 2; if ((p = (U_CHAR *) xrealloc (obuf->buf, i)) == NULL) return NULL; obuf->bufp = p + (obuf->bufp - obuf->buf); obuf->buf = p; obuf->length = i; return p;} /* * install a name in the main hash table, even if it is already there. * name stops with first non alphanumeric, except leading '#'. * caller must check against redefinition if that is desired. * delete() removes things installed by install() in fifo order. * this is important because of the `defined' special symbol used * in #if, and also if pushdef/popdef directives are ever implemented. */HASHNODE *install (name, type, value) U_CHAR *name; int type; int value; /* watch out here if sizeof(U_CHAR *) != sizeof (int) */{ HASHNODE *hp; int i, len = 0, bucket; register U_CHAR *p; p = name; while (is_idchar[*p]) p++; len = p - name; i = sizeof (HASHNODE) + len + 1; hp = (HASHNODE *) xmalloc (i); bucket = hashf(name, len, HASHSIZE); hp->bucket_hdr = &hashtab[bucket]; hp->next = hashtab[bucket]; hashtab[bucket] = hp; hp->prev = NULL; if (hp->next != NULL) hp->next->prev = hp; hp->type = type; hp->length = len; hp->value.ival = value; hp->name = ((U_CHAR *) hp) + sizeof (HASHNODE); bcopy (name, hp->name, len); return hp;}/* * find the most recent hash node for name name (ending with first * non-identifier char) installed by install */HASHNODE *lookup (name) U_CHAR *name;{ register U_CHAR *bp; register HASHNODE *bucket; int len; for (bp = name; is_idchar[*bp]; bp++) ; len = bp - name; bucket = hashtab[hashf(name, len, HASHSIZE)]; while (bucket) { if (bucket->length == len && strncmp(bucket->name, name, len) == 0) return bucket; bucket = bucket->next; } return NULL;}/* * Delete a hash node. Some weirdness to free junk from macros. * More such weirdness will have to be added if you define more hash * types that need it. */delete(hp) HASHNODE *hp;{ if (hp->prev != NULL) hp->prev->next = hp->next; if (hp->next != NULL) hp->next->prev = hp->prev; /* make sure that the bucket chain header that the deleted guy was on points to the right thing afterwards. */ if (hp == *hp->bucket_hdr) *hp->bucket_hdr = hp->next; if (hp->type == T_MACRO) { DEFINITION *d = hp->value.defn; struct reflist *ap, *nextap; for (ap = d->pattern; ap != NULL; ap = nextap) { nextap = ap->next; free (ap); } free (d); }}/* * return hash function on name. must be compatible with the one * computed a step at a time, elsewhere */inthashf(name, len, hashsize) register U_CHAR *name; register int len; int hashsize;{ register int r = 0; while (len--) r = HASHSTEP(r, *name++); return MAKE_POS(r) % hashsize;}/* * initialize random junk in the hash table and maybe other places */initialize_random_junk(){ register int i; /* * Set up is_idchar and is_idstart tables. These should be * faster than saying (is_alpha(c) || c == '_'), etc. * Must do set up these things before calling any routines tthat * refer to them. */ for (i = 'a'; i <= 'z'; i++) { ++is_idchar[i - 'a' + 'A']; ++is_idchar[i]; ++is_idstart[i - 'a' + 'A']; ++is_idstart[i]; } for (i = '0'; i <= '9'; i++) ++is_idchar[i]; ++is_idchar['_']; ++is_idstart['_']; /* horizontal space table */ ++is_hor_space[' ']; ++is_hor_space['\t']; install("__LINE__", T_SPECLINE, 0); install("__DATE__", T_DATE, 0); install("__FILE__", T_FILE, 0); install("__TIME__", T_TIME, 0);#ifdef vax make_definition("vax 1");#endif#ifdef unix make_definition("unix 1");#endif /* is there more? */ }/* * process a given definition string, for initialization */make_definition(str) U_CHAR *str;{ FILE_BUF *ip; struct keyword_table *kt; ip = &instack[indepth++]; ip->fname = "*Initialization*"; ip->buf = ip->bufp = str; ip->length = strlen(str); ip->lineno = 1; for (kt = keyword_table; kt->type != T_DEFINE; kt++) ; /* pass NULL as output ptr to do_define since we KNOW it never does any output.... */ do_define (str, str + strlen(str) /* - 1 JF */ , NULL, kt); --indepth;}/* JF, this does the work for the -U option */make_undef(str) U_CHAR *str;{ FILE_BUF *ip; struct keyword_table *kt; ip = &instack[indepth++]; ip->fname = "*undef*"; ip->buf = ip->bufp = str; ip->length = strlen(str); ip->lineno = 1; for(kt = keyword_table; kt->type != T_UNDEF; kt++) ; do_undef(str,str + strlen(str) - 1, NULL, kt); --indepth;}#ifndef BSD#ifndef BSTRINGvoidbzero (b, length) register char *b; register int length;{#ifdef VMS short zero = 0; long max_str = 65535; while (length > max_str) { (void) LIB$MOVC5 (&zero, &zero, &zero, &max_str, b); length -= max_str; b += max_str; } (void) LIB$MOVC5 (&zero, &zero, &zero, &length, b);#else while (length-- > 0) *b++ = 0;#endif /* not VMS */}void bcopy (b1, b2, length) register char *b1; register char *b2; register int length;{#ifdef VMS long max_str = 65535; while (length > max_str) { (void) LIB$MOVC3 (&max_str, b1, b2); length -= max_str; b1 += max_str; b2 += max_str; } (void) LIB$MOVC3 (&length, b1, b2);#else while (length-- > 0) *b2++ = *b1++;#endif /* not VMS */} intbcmp (b1, b2, length) /* This could be a macro! */ register char *b1; register char *b2; register int length; {#ifdef VMS struct dsc$descriptor_s src1 = {length, DSC$K_DTYPE_T, DSC$K_CLASS_S, b1}; struct dsc$descriptor_s src2 = {length, DSC$K_DTYPE_T, DSC$K_CLASS_S, b2}; return STR$COMPARE (&src1, &src2);#else while (length-- > 0) if (*b1++ != *b2++) return 1; return 0;#endif /* not VMS */}#endif /* not BSTRING */#endif /* not BSD */voidfatal (str, arg) char *str, *arg;{ fprintf (stderr, "%s: ", progname); fprintf (stderr, str, arg); fprintf (stderr, "\n"); exit (FATAL_EXIT_CODE);}voidperror_with_name (name) char *name;{ extern int errno, sys_nerr; extern char *sys_errlist[]; fprintf (stderr, "%s: ", progname); if (errno < sys_nerr) fprintf (stderr, "%s for %s\n", sys_errlist[errno], name); else fprintf (stderr, "cannot open %s\n", sys_errlist[errno], name);}voidpfatal_with_name (name) char *name;{ perror_with_name (name); exit (FATAL_EXIT_CODE);}static voidmemory_full (){ fatal ("Memory exhausted.");}char *xmalloc (size) int size;{ extern char *malloc (); register char *ptr = malloc (size); if (ptr != 0) return (ptr); memory_full (); /*NOTREACHED*/}char *xrealloc (old, size) char *old; int size;{ extern char *realloc (); register char *ptr = realloc (old, size); if (ptr != 0) return (ptr); memory_full (); /*NOTREACHED*/}char *xcalloc (number, size) int number, size;{ extern char *malloc (); register int total = number * size; register char *ptr = malloc (total); if (ptr != 0) { bzero (ptr, total); return (ptr); } memory_full (); /*NOTREACHED*/}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -