nlist.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include <u.h>
  10. #include <libc.h>
  11. #include <stdio.h>
  12. #include "cpp.h"
  13. extern int getopt(int, char **, char *);
  14. extern char *optarg;
  15. extern int optind;
  16. int verbose;
  17. int Mflag;
  18. int Cplusplus;
  19. int nolineinfo;
  20. Nlist *kwdefined;
  21. char wd[128];
  22. #define NLSIZE 128
  23. Nlist *nlist[NLSIZE];
  24. struct kwtab {
  25. char *kw;
  26. int val;
  27. int flag;
  28. } kwtab[] = {
  29. "if", KIF, ISKW,
  30. "ifdef", KIFDEF, ISKW,
  31. "ifndef", KIFNDEF, ISKW,
  32. "elif", KELIF, ISKW,
  33. "else", KELSE, ISKW,
  34. "endif", KENDIF, ISKW,
  35. "include", KINCLUDE, ISKW,
  36. "define", KDEFINE, ISKW,
  37. "undef", KUNDEF, ISKW,
  38. "line", KLINE, ISKW,
  39. "error", KERROR, ISKW,
  40. "warning", KWARNING, ISKW, // extension to ANSI
  41. "pragma", KPRAGMA, ISKW,
  42. "eval", KEVAL, ISKW,
  43. "defined", KDEFINED, ISDEFINED+ISUNCHANGE,
  44. "__LINE__", KLINENO, ISMAC+ISUNCHANGE,
  45. "__FILE__", KFILE, ISMAC+ISUNCHANGE,
  46. "__DATE__", KDATE, ISMAC+ISUNCHANGE,
  47. "__TIME__", KTIME, ISMAC+ISUNCHANGE,
  48. "__STDC__", KSTDC, ISUNCHANGE,
  49. NULL
  50. };
  51. unsigned long namebit[077+1];
  52. Nlist *np;
  53. void
  54. setup(int argc, char **argv)
  55. {
  56. struct kwtab *kp;
  57. Nlist *np;
  58. Token t;
  59. int fd, i;
  60. char *fp, *dp;
  61. Tokenrow tr;
  62. char *objtype;
  63. char *includeenv;
  64. int firstinclude;
  65. static char nbuf[40];
  66. static Token deftoken[1] = {{ NAME, 0, 0, 0, 7, (uchar*)"defined" }};
  67. static Tokenrow deftr = { deftoken, deftoken, deftoken+1, 1 };
  68. int debuginclude = 0;
  69. int nodot = 0;
  70. char xx[2] = { 0, 0};
  71. for (kp=kwtab; kp->kw; kp++) {
  72. t.t = (uchar*)kp->kw;
  73. t.len = strlen(kp->kw);
  74. np = lookup(&t, 1);
  75. np->flag = kp->flag;
  76. np->val = kp->val;
  77. if (np->val == KDEFINED) {
  78. kwdefined = np;
  79. np->val = NAME;
  80. np->vp = &deftr;
  81. np->ap = 0;
  82. }
  83. }
  84. /*
  85. * For Plan 9, search /objtype/include, then /sys/include
  86. * (Note that includelist is searched from high end to low)
  87. */
  88. if ((objtype = getenv("objtype"))){
  89. snprintf(nbuf, sizeof nbuf, "/%s/include", objtype);
  90. includelist[1].file = nbuf;
  91. includelist[1].always = 1;
  92. } else {
  93. includelist[1].file = NULL;
  94. error(WARNING, "Unknown $objtype");
  95. }
  96. if (getwd(wd, sizeof(wd))==0)
  97. wd[0] = '\0';
  98. includelist[0].file = "/sys/include";
  99. includelist[0].always = 1;
  100. firstinclude = NINCLUDE-2;
  101. if ((includeenv=getenv("include")) != NULL) {
  102. char *cp;
  103. includeenv = strdup(includeenv);
  104. for (;firstinclude>0; firstinclude--) {
  105. cp = strtok(includeenv, " ");
  106. if (cp==NULL)
  107. break;
  108. includelist[firstinclude].file = cp;
  109. includelist[firstinclude].always = 1;
  110. includeenv = NULL;
  111. }
  112. }
  113. setsource("", -1, 0);
  114. ARGBEGIN {
  115. case 'N':
  116. for (i=0; i<NINCLUDE; i++)
  117. if (includelist[i].always==1)
  118. includelist[i].deleted = 1;
  119. break;
  120. case 'I':
  121. for (i=firstinclude; i>=0; i--) {
  122. if (includelist[i].file==NULL) {
  123. includelist[i].always = 1;
  124. includelist[i].file = ARGF();
  125. break;
  126. }
  127. }
  128. if (i<0)
  129. error(WARNING, "Too many -I directives");
  130. break;
  131. case 'D':
  132. case 'U':
  133. setsource("<cmdarg>", -1, ARGF());
  134. maketokenrow(3, &tr);
  135. gettokens(&tr, 1);
  136. doadefine(&tr, ARGC());
  137. unsetsource();
  138. break;
  139. case 'M':
  140. Mflag++;
  141. break;
  142. case 'V':
  143. verbose++;
  144. break;
  145. case '+':
  146. Cplusplus++;
  147. break;
  148. case 'i':
  149. debuginclude++;
  150. break;
  151. case 'P':
  152. nolineinfo++;
  153. break;
  154. case '.':
  155. nodot++;
  156. break;
  157. default:
  158. xx[0] = ARGC();
  159. error(FATAL, "Unknown argument '%s'", xx);
  160. break;
  161. } ARGEND
  162. dp = ".";
  163. fp = "<stdin>";
  164. fd = 0;
  165. if (argc > 2)
  166. error(FATAL, "Too many file arguments; see cpp(1)");
  167. if (argc > 0) {
  168. if ((fp = strrchr(argv[0], '/')) != NULL) {
  169. int len = fp - argv[0];
  170. dp = (char*)newstring((uchar*)argv[0], len+1, 0);
  171. dp[len] = '\0';
  172. }
  173. fp = (char*)newstring((uchar*)argv[0], strlen(argv[0]), 0);
  174. if ((fd = open(fp, 0)) < 0)
  175. error(FATAL, "Can't open input file %s", fp);
  176. }
  177. if (argc > 1) {
  178. int fdo = create(argv[1], 1, 0666);
  179. if (fdo<0)
  180. error(FATAL, "Can't open output file %s", argv[1]);
  181. dup(fdo, 1);
  182. }
  183. if (Mflag)
  184. setobjname(fp);
  185. includelist[NINCLUDE-1].always = 0;
  186. includelist[NINCLUDE-1].file = dp;
  187. if(nodot)
  188. includelist[NINCLUDE-1].deleted = 1;
  189. setsource(fp, fd, NULL);
  190. if (debuginclude) {
  191. for (i=0; i<NINCLUDE; i++)
  192. if (includelist[i].file && includelist[i].deleted==0)
  193. error(WARNING, "Include: %s", includelist[i].file);
  194. }
  195. }
  196. Nlist *
  197. lookup(Token *tp, int install)
  198. {
  199. unsigned int h;
  200. Nlist *np;
  201. uint8_t *cp, *cpe;
  202. h = 0;
  203. for (cp=tp->t, cpe=cp+tp->len; cp<cpe; )
  204. h += *cp++;
  205. h %= NLSIZE;
  206. np = nlist[h];
  207. while (np) {
  208. if (*tp->t==*np->name && tp->len==np->len
  209. && strncmp((char*)tp->t, (char*)np->name, tp->len)==0)
  210. return np;
  211. np = np->next;
  212. }
  213. if (install) {
  214. np = new(Nlist);
  215. np->val = 0;
  216. np->vp = NULL;
  217. np->ap = NULL;
  218. np->flag = 0;
  219. np->len = tp->len;
  220. np->name = newstring(tp->t, tp->len, 0);
  221. np->next = nlist[h];
  222. nlist[h] = np;
  223. quickset(tp->t[0], tp->len>1? tp->t[1]:0);
  224. return np;
  225. }
  226. return NULL;
  227. }