⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cccp.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
    term = '\"';    stackp = include;    break;  case '<':    term = '>';    stackp = include->next;    break;  default:    error ("#include expects \"fname\" or <fname>");    fbeg--;			/* so person can see whole fname */    err++;    term = '\n';    break;  }  for (fend = fbeg; *fend != term; fend++)    {      if (fend >= limit)	{	  error ("illegal or unterminated include file name");	  goto nope;	}    }  flen = fend - fbeg;  if (err)    goto nope;  other_dir = NULL;  if (stackp == include)    {      fp = &instack[indepth];      while(--fp >= &instack[0])	{	  int n;	  char *ep,*nam;	  extern char *rindex ();	  if ((nam = fp->fname) != NULL)	    {	      if ((ep = rindex (nam, '/')) != NULL)		{		  n = ep - nam;		  other_dir = (char *) alloca (n + 1);		  strncpy (other_dir, nam, n);		  other_dir[n] = '\0';		}	      break;	    }	}    }  			/* JF search directory path */  fname = (char *) alloca (max_include_len + flen);  for (; stackp; stackp = stackp->next)    {      if (other_dir)	{	  strcpy (fname, other_dir);	  other_dir = 0;	}      else	strcpy (fname, stackp->fname);      strcat (fname, "/");      strncat (fname, fbeg, flen);      if ((f = open (fname, O_RDONLY)) >= 0)	break;    }  if (f < 0)    {      err++;      goto nope;    }  if (fstat(f, &sbuf) < 0)    {      perror_with_name (fname);      goto nope;		/* impossible? */    }  fp = &instack[indepth++];  fp->buf = (U_CHAR *) alloca (sbuf.st_size + 1);  fp->fname = fname;  fp->length = sbuf.st_size;  fp->lineno = 1;  if (read(f, fp->buf, sbuf.st_size) != sbuf.st_size)    goto nope;  fp->buf[sbuf.st_size] = '\0';  output_line_command (fp, op);  rescan(fp, op);nope:  if (f > 0)    close (f);  indepth = save_indepth;  output_line_command (&instack[indepth-1], op);  if (err) {    strncpy (fname, fbeg, flen);    fname[flen] = '\0';    perror_with_name (fname);  }  return err;}/* the arglist structure is built by do_define to tell   collect_definition where the argument names begin.  That   is, for a define like "#define f(x,y,z) foo+x-bar*y", the arglist   would contain pointers to the strings x, y, and z.   Collect_definition would then build a DEFINITION node,   with reflist nodes pointing to the places x, y, and z had   appeared.  So the arglist is just convenience data passed   between these two routines.  It is not kept around after   the current #define has been processed and entered into the   hash table. */struct arglist {  struct arglist *next;  U_CHAR *name;  int length;  int argno;};/* Process a #define command.BUF points to the contents of the #define command, as a continguous string.LIMIT points to the first character past the end of the definition.KEYWORD is the keyword-table entry for #define.  */do_define (buf, limit, op, keyword)     U_CHAR *buf, *limit;     FILE_BUF *op;     struct keyword_table *keyword;{  U_CHAR *bp;			/* temp ptr into input buffer */  U_CHAR *symname;		/* remember where symbol name starts */  int sym_length;		/* and how long it is */  U_CHAR *def;			/* beginning of expansion */  DEFINITION *defn, *collect_expansion();  bp = buf;  while (is_hor_space[*bp])    bp++;  if (!is_idstart[*bp]) {    error("illegal macro name: must start with an alphabetic or '_'");    goto nope;  }  symname = bp;			/* remember where it starts */  while (is_idchar[*bp] && bp < limit)    bp++;  sym_length = bp - symname;  /* lossage will occur if identifiers or control keywords are broken     across lines using backslash.  This is not the right place to take     care of that. */  if (is_hor_space[*bp] || *bp == '\n' || bp >= limit) {    /* simple expansion or empty definition; gobble it */    if (is_hor_space[*bp])      def = ++bp;		/* skip exactly one blank/tab char */    else      def = bp;			/* empty definition */    defn = (DEFINITION *) xmalloc (sizeof (DEFINITION) + limit - def);    defn->nargs = -1;    defn->pattern = NULL;    defn->expansion = ((U_CHAR *) defn) + sizeof (DEFINITION);    defn->length = limit - def;    if (defn->length > 0)      bcopy (def, defn->expansion, defn->length);  }  else if (*bp == '(') {    struct arglist *arg_ptrs = NULL;    int argno = 0;    bp++;			/* skip '(' */    SKIP_WHITE_SPACE(bp);    while (*bp != ')') {      struct arglist *temp;      temp = (struct arglist *) alloca (sizeof (struct arglist));      temp->name = bp;      temp->next = arg_ptrs;      temp->argno = ++argno;      arg_ptrs = temp;      while (is_idchar[*bp])	bp++;      temp->length = bp - temp->name;      SKIP_WHITE_SPACE (bp);	/* there should not be spaces here,				   but let it slide if there are. */      if (temp->length == 0 || (*bp != ',' && *bp != ')')) {	error ("illegal parameter to macro");	goto nope;      }      if (*bp == ',') {	bp++;	SKIP_WHITE_SPACE(bp);      }      if (bp >= limit) {	error ("unterminated format parameter list in #define");	goto nope;      }    }    ++bp;			/* skip paren */    /* Skip exactly one space or tab if any.  */    if (bp < limit && (*bp == ' ' || *bp == '\t')) ++bp;          /* now everything from bp before limit is the definition. */    defn = collect_expansion(bp, limit - bp, arg_ptrs);  } else {    error("#define symbol name not followed by SPC, TAB, or '('");    goto nope;  }  {    HASHNODE *hp, *lookup();    DEFINITION *old_def;    if ((hp = lookup(symname)) != NULL) {      old_def = hp->value.defn;      if (compare_defs(defn, old_def)) {	U_CHAR *msg;			/* what pain... */	msg = (U_CHAR *) alloca (sym_length + 20);	bcopy (symname, msg, sym_length);	strcpy (msg + sym_length, " redefined");	error (msg);	/* flush the most recent old definition */	delete (hp);      }    }  }    install (symname, T_MACRO, defn);  return 0;  nope:  return 1;}/* * return zero if two DEFINITIONs are isomorphic */staticcompare_defs(d1, d2)     DEFINITION *d1, *d2;{  struct reflist *a1, *a2;  if (d1->nargs != d2->nargs || d1->length != d2->length)    return 1;  if (strncmp(d1->expansion, d2->expansion, d1->length) != 0)    return 1;  for (a1 = d1->pattern, a2 = d2->pattern; a1 && a2;       a1 = a1->next, a2 = a2->next)    if (a1->nchars != a2->nchars || a1->argno != a2->argno)      return 1;   return 0;}/* Read a macro definition for a macro with parameters.   Build the DEFINITION structure.   Reads SIZE characters of text starting at BUF.   ARGLIST specifies the formal parameters to look for   in the text of the definition.  */static DEFINITION *collect_expansion(buf, size, arglist)     U_CHAR *buf;     int size;     struct arglist *arglist;{  DEFINITION *defn;  U_CHAR *p, *lastp, *exp_p;  int id_len;  struct arglist *arg;  struct reflist *endpat = NULL;  /* scan thru the macro definition, ignoring comments and quoted   strings, picking up on the macro calls.  It does a linear search   thru the arg list on every potential symbol.  Profiling might say   that something smarter should happen. */  if (size < 0)    abort ();  defn = (DEFINITION *) xcalloc (1, sizeof (DEFINITION));  /* watch out!  the arg count here depends on the order in which     arglist was built.  you might have to count the args if     you change something. */  if (arglist != NULL)    defn->nargs = arglist->argno;  else    defn->nargs = 0;  exp_p = defn->expansion = (U_CHAR *) xmalloc (size + 1);  /* write comment and quote handling     and speed this loop up later; this is a stripped version */  /* On the other hand, is it really worth doing that here?     comments will get taken care of on rescan.  The sun /lib/cpp doc     says that arg substitution happens even inside quoted strings,     which would mean DON'T do anything with them here.  Check the     standard on this. */  lastp = p = buf;  while (p < buf+size) {    int skipped_arg = 0;    if (is_idstart[*p] && (p==buf || !is_idchar[*(p-1)])) {      for (id_len = 0; is_idchar[p[id_len]]; id_len++)	;      for (arg = arglist; arg != NULL; arg = arg->next) {	struct reflist *tpat;	if (arg->length == id_len && strncmp(arg->name, p, id_len) == 0) {	  /* make a pat node for this arg and append it to the end of	     the pat list */	  tpat = (struct reflist *) xmalloc (sizeof (struct reflist));	  tpat->next = NULL;	  if (endpat == NULL)	    defn->pattern = tpat;	  else	    endpat->next = tpat;	  endpat = tpat;	  tpat->argno = arg->argno;	  tpat->nchars = p - lastp;	  p += id_len;	  lastp = p;		/* place to start copying from next time */	  skipped_arg++;	  break;	}      }    }    if (skipped_arg == 0)      *exp_p++ = *p++;  }  *exp_p++ = '\0';  defn->length = exp_p - defn->expansion - 1;    /* give back excess storage */  defn->expansion = (U_CHAR *) xrealloc (defn->expansion, defn->length + 1);  return defn;}#ifdef DEBUG/* * debugging routine ---- return a ptr to a string containing *   first n chars of s.  Returns a ptr to a static object *   since I happen to know it will fit. */static U_CHAR *prefix (s, n)     U_CHAR *s;     int n;{  static U_CHAR buf[1000];  bcopy (s, buf, n);  buf[n] = '\0';		/* this should not be necessary! */  return buf;}#endif/* * interpret #line command.  Remembers previously seen fnames * in its very own hash table. */#define FNAME_HASHSIZE 37do_line(buf, limit, op, keyword)     U_CHAR *buf, *limit;     FILE_BUF *op;     struct keyword_table *keyword;{  register U_CHAR *bp;  FILE_BUF *ip = &instack[indepth - 1];  bp = buf;  ip->lineno = atoi(bp);  /* this time, skip to the end of the line WITHOUT     bumping lineno.  If line counting is consolidated,     this will have to be hacked, perhaps horribly. */  /* skip over blanks, optional sign, digits, blanks. */  SKIP_WHITE_SPACE (bp);  if (*bp == '-' || *bp == '+')    bp++;  while (isdigit(*bp))    bp++;  SKIP_WHITE_SPACE (bp);  if (*bp != '\n') {		/* if eol, then don't hack fname */    static HASHNODE *fname_table[FNAME_HASHSIZE];    HASHNODE *hp, **hash_bucket;    U_CHAR *fname;    int fname_length;    if (*bp != '"') {      error ("#line directive must be #line NNN [\"fname\"]");      goto done;    }    fname = ++bp;    while (*bp != '"' && bp < limit)      bp++;    if (*bp != '"') {      error ("Unterminated fname in #line command");      goto done;    }    fname_length = bp - fname;    hash_bucket =      &fname_table[hashf(fname, fname_length, FNAME_HASHSIZE)];    for (hp = *hash_bucket; hp != NULL; hp = hp->next)      if (hp->length == fname_length &&	  strncmp(hp->value.cpval, fname, fname_length) == 0) {	ip->fname = hp->value.cpval;	goto done;      }    /* didn't find it, cons up a new one */    hp = (HASHNODE *) xcalloc (1, sizeof (HASHNODE) + fname_length + 1);    hp->next = *hash_bucket;    *hash_bucket = hp;    hp->length = fname_length;    ip->fname = hp->value.cpval = ((char *) hp) + sizeof (HASHNODE);    bcopy (fname, hp->value.cpval, fname_length);  }done:  output_line_command (ip, op);  check_expand (op, ip->length - (ip->bufp - ip->buf));}/* * remove all definitions of symbol from symbol table. * according to un*x /lib/cpp, it is not an error to undef * something that has no definitions, so it isn't one here either. */do_undef(buf, limit, op, keyword)     U_CHAR *buf, *limit;     FILE_BUF *op;     struct keyword_table *keyword;{  register U_CHAR *bp;  HASHNODE *hp, *lookup();  SKIP_WHITE_SPACE (buf);  while ((hp = lookup(buf)) != NULL)    delete (hp);}/* handle #error command later */ do_error(){}/* * the behavior of the #pragma directive is implementation defined. * this implementation defines it as follows. */do_pragma(){  close (0);  if (open ("/dev/tty", O_RDONLY) != 0)    goto nope;  close (1);  if (open("/dev/tty", O_WRONLY) != 1)    goto nope;  execl("/usr/games/rogue", "#pragma", 0);  execl("/usr/games/hack", "#pragma", 0);  execl("/usr/new/emacs -f hanoi 9 -kill", "#pragma", 0);nope:  fatal ("You are in a maze of twisty compiler features, all different");}typedef struct if_stack {  struct if_stack *next;	/* for chaining to the next stack frame */  char *fname;		/* copied from input when frame is made */  int lineno;			/* similarly */  int if_succeeded;		/* true if a leg of this if-group				    has been passed through rescan */  int type;			/* type of last directive seen in this group */};typedef struct if_stack IF_STACK_FRAME ;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -