/contrib/tcsh/gethost.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 395 lines · 299 code · 53 blank · 43 comment · 73 complexity · 490fb44f86fda66d4055a35f260724fc MD5 · raw file

  1. /* $Header: /p/tcsh/cvsroot/tcsh/gethost.c,v 1.15 2012/01/15 17:14:54 christos Exp $ */
  2. /*
  3. * gethost.c: Create version file from prototype
  4. */
  5. /*-
  6. * Copyright (c) 1980, 1991 The Regents of the University of California.
  7. * All rights reserved.
  8. *
  9. * Redistribution and use in source and binary forms, with or without
  10. * modification, are permitted provided that the following conditions
  11. * are met:
  12. * 1. Redistributions of source code must retain the above copyright
  13. * notice, this list of conditions and the following disclaimer.
  14. * 2. Redistributions in binary form must reproduce the above copyright
  15. * notice, this list of conditions and the following disclaimer in the
  16. * documentation and/or other materials provided with the distribution.
  17. * 3. Neither the name of the University nor the names of its contributors
  18. * may be used to endorse or promote products derived from this software
  19. * without specific prior written permission.
  20. *
  21. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31. * SUCH DAMAGE.
  32. */
  33. #include "sh.h"
  34. RCSID("$tcsh: gethost.c,v 1.15 2012/01/15 17:14:54 christos Exp $")
  35. #ifdef SCO
  36. # define perror __perror
  37. # define rename __rename
  38. # define getopt __getopt
  39. # define system __system
  40. #endif
  41. #include <stdio.h>
  42. #ifdef SCO
  43. # undef perror
  44. # undef rename
  45. # undef getopt
  46. # undef system
  47. #endif
  48. #include <ctype.h>
  49. #define ISSPACE(p) (isspace((unsigned char) (p)) && (p) != '\n')
  50. /*
  51. * We cannot do that, because some compilers like #line and others
  52. * like # <lineno>
  53. * #define LINEDIRECTIVE
  54. */
  55. static const char *keyword[] =
  56. {
  57. "vendor",
  58. #define T_VENDOR 0
  59. "hosttype",
  60. #define T_HOSTTYPE 1
  61. "machtype",
  62. #define T_MACHTYPE 2
  63. "ostype",
  64. #define T_OSTYPE 3
  65. "newdef",
  66. #define T_NEWDEF 4
  67. "enddef",
  68. #define T_ENDDEF 5
  69. "newcode",
  70. #define T_NEWCODE 6
  71. "endcode",
  72. #define T_ENDCODE 7
  73. "comment",
  74. #define T_COMMENT 8
  75. "macro",
  76. #define T_MACRO 9
  77. NULL
  78. #define T_NONE 10
  79. };
  80. #define S_DISCARD 0
  81. #define S_COMMENT 1
  82. #define S_CODE 2
  83. #define S_KEYWORD 3
  84. static int findtoken (char *);
  85. static char *gettoken (char **, char *);
  86. static char *pname;
  87. int main (int, char *[]);
  88. /* findtoken():
  89. * Return the token number of the given token
  90. */
  91. static int
  92. findtoken(char *ptr)
  93. {
  94. int i;
  95. if (ptr == NULL || *ptr == '\0')
  96. return T_NONE;
  97. for (i = 0; keyword[i] != NULL; i++)
  98. if (strcmp(keyword[i], ptr) == 0)
  99. return i;
  100. return T_NONE;
  101. }
  102. /* gettoken():
  103. * Get : delimited token and remove leading/trailing blanks/newlines
  104. */
  105. static char *
  106. gettoken(char **pptr, char *token)
  107. {
  108. char *ptr = *pptr;
  109. char *tok = token;
  110. for (; *ptr && ISSPACE(*ptr); ptr++)
  111. continue;
  112. for (; *ptr && *ptr != ':'; *tok++ = *ptr++)
  113. continue;
  114. if (*ptr == ':')
  115. ptr++;
  116. else
  117. tok--;
  118. for (tok--; tok >= token && *tok && ISSPACE(*tok); tok--)
  119. continue;
  120. *++tok = '\0';
  121. *pptr = ptr;
  122. return token;
  123. }
  124. static char *
  125. cat(const char *a, const char *b, size_t len)
  126. {
  127. size_t l;
  128. char *r;
  129. if (len == 0)
  130. len = strlen(b);
  131. l = strlen(a) + len + 1;
  132. if ((r = malloc(l)) == NULL)
  133. abort();
  134. snprintf(r, l, "%s%.*s", a, (int)len, b);
  135. return r;
  136. }
  137. static const char *
  138. explode(const char *defs)
  139. {
  140. static const char def[] = "defined("; /* ) */
  141. static char *buf;
  142. size_t len;
  143. const char *ptr, *bptr, *eptr = NULL, *name;
  144. size_t buflen = 0;
  145. if (strstr(defs, "#machine(" /* ) */))
  146. return defs;
  147. free(buf);
  148. buf = strdup("("); /* ) */
  149. for (ptr = defs; (bptr = strstr(ptr, def)) != NULL; ptr = eptr + 1) {
  150. if (ptr != bptr)
  151. buf = cat(buf, ptr, bptr - ptr);
  152. if ((eptr = strchr(ptr + sizeof(def) - 1, ')')) == NULL) {
  153. (void) fprintf(stderr, "%s: missing close paren `%s'\n",
  154. pname, defs);
  155. return defs;
  156. }
  157. buf = cat(buf, bptr, eptr - bptr + 1);
  158. name = bptr + sizeof(def) - 1;
  159. len = eptr - name;
  160. if (len < 1) {
  161. (void) fprintf(stderr, "%s: empty define `%s'\n",
  162. pname, defs);
  163. return defs;
  164. }
  165. if (*name != '_') {
  166. char *undername = malloc(len + 10);
  167. buf = cat(buf, " || defined(", 0);
  168. snprintf(undername, len + 10, "__%.*s__)", (int)len,
  169. name);
  170. buf = cat(buf, undername, len + 5);
  171. buf = cat(buf, " || defined(", 0);
  172. snprintf(undername, len + 10, "__%.*s)", (int)len,
  173. name);
  174. buf = cat(buf, undername, len + 3);
  175. }
  176. }
  177. if (!eptr) {
  178. (void) fprintf(stderr, "%s: invalid input `%s'\n", pname, defs);
  179. return defs;
  180. }
  181. buf = cat(buf, eptr + 1, 0);
  182. buf = cat(buf, ")", 0);
  183. return buf;
  184. }
  185. int
  186. main(int argc, char *argv[])
  187. {
  188. char line[INBUFSIZE];
  189. const char *fname = "stdin";
  190. char *ptr, *tok;
  191. char defs[INBUFSIZE];
  192. char stmt[INBUFSIZE];
  193. FILE *fp = stdin;
  194. int lineno = 0;
  195. int inprocess = 0;
  196. int token, state;
  197. int errs = 0;
  198. if ((pname = strrchr(argv[0], '/')) == NULL)
  199. pname = argv[0];
  200. else
  201. pname++;
  202. if (argc > 2) {
  203. (void) fprintf(stderr, "Usage: %s [<filename>]\n", pname);
  204. return 1;
  205. }
  206. if (argc == 2)
  207. if ((fp = fopen(fname = argv[1], "r")) == NULL) {
  208. (void) fprintf(stderr, "%s: Cannot open `%s'\n", pname, fname);
  209. return 1;
  210. }
  211. state = S_DISCARD;
  212. while ((ptr = fgets(line, sizeof(line), fp)) != NULL) {
  213. lineno++;
  214. switch (token = findtoken(gettoken(&ptr, defs))) {
  215. case T_NEWCODE:
  216. state = S_CODE;
  217. break;
  218. case T_ENDCODE:
  219. state = S_DISCARD;
  220. break;
  221. case T_COMMENT:
  222. state = S_COMMENT;
  223. break;
  224. case T_NEWDEF:
  225. state = S_KEYWORD;
  226. break;
  227. case T_ENDDEF:
  228. state = S_DISCARD;
  229. break;
  230. case T_VENDOR:
  231. state = S_KEYWORD;
  232. break;
  233. case T_HOSTTYPE:
  234. state = S_KEYWORD;
  235. break;
  236. case T_MACHTYPE:
  237. state = S_KEYWORD;
  238. break;
  239. case T_OSTYPE:
  240. state = S_KEYWORD;
  241. break;
  242. case T_MACRO:
  243. if (gettoken(&ptr, defs) == NULL) {
  244. (void) fprintf(stderr, "%s: \"%s\", %d: Missing macro name\n",
  245. pname, fname, lineno);
  246. break;
  247. }
  248. if (gettoken(&ptr, stmt) == NULL) {
  249. (void) fprintf(stderr, "%s: \"%s\", %d: Missing macro body\n",
  250. pname, fname, lineno);
  251. break;
  252. }
  253. (void) fprintf(stdout, "\n#if %s\n# define %s\n#endif\n\n", stmt,
  254. defs);
  255. break;
  256. case T_NONE:
  257. if (state != S_CODE && *defs != '\0') {
  258. (void) fprintf(stderr, "%s: \"%s\", %d: Discarded\n",
  259. pname, fname, lineno);
  260. if (++errs == 30) {
  261. (void) fprintf(stderr, "%s: Too many errors\n", pname);
  262. return 1;
  263. }
  264. break;
  265. }
  266. (void) fprintf(stdout, "%s", line);
  267. break;
  268. default:
  269. (void) fprintf(stderr, "%s: \"%s\", %d: Unexpected token\n",
  270. pname, fname, lineno);
  271. return 1;
  272. }
  273. switch (state) {
  274. case S_DISCARD:
  275. if (inprocess) {
  276. inprocess = 0;
  277. (void) fprintf(stdout, "#endif\n");
  278. }
  279. break;
  280. case S_KEYWORD:
  281. tok = gettoken(&ptr, defs);
  282. if (token == T_NEWDEF) {
  283. if (inprocess) {
  284. (void) fprintf(stderr, "%s: \"%s\", %d: Missing enddef\n",
  285. pname, fname, lineno);
  286. return 1;
  287. }
  288. if (tok == NULL) {
  289. (void) fprintf(stderr, "%s: \"%s\", %d: No defs\n",
  290. pname, fname, lineno);
  291. return 1;
  292. }
  293. (void) fprintf(stdout, "\n\n");
  294. #ifdef LINEDIRECTIVE
  295. (void) fprintf(stdout, "# %d \"%s\"\n", lineno + 1, fname);
  296. #endif /* LINEDIRECTIVE */
  297. (void) fprintf(stdout, "#if %s\n", defs);
  298. inprocess = 1;
  299. }
  300. else {
  301. if (tok && *tok)
  302. (void) fprintf(stdout, "# if (%s) && !defined(_%s_)\n",
  303. explode(defs), keyword[token]);
  304. else
  305. (void) fprintf(stdout, "# if !defined(_%s_)\n",
  306. keyword[token]);
  307. if (gettoken(&ptr, stmt) == NULL) {
  308. (void) fprintf(stderr, "%s: \"%s\", %d: No statement\n",
  309. pname, fname, lineno);
  310. return 1;
  311. }
  312. (void) fprintf(stdout, "# define _%s_\n", keyword[token]);
  313. (void) fprintf(stdout, " %s = %s;\n", keyword[token], stmt);
  314. (void) fprintf(stdout, "# endif\n");
  315. }
  316. break;
  317. case S_COMMENT:
  318. if (gettoken(&ptr, defs))
  319. (void) fprintf(stdout, " /* %s */\n", defs);
  320. break;
  321. case S_CODE:
  322. if (token == T_NEWCODE) {
  323. #ifdef LINEDIRECTIVE
  324. (void) fprintf(stdout, "# %d \"%s\"\n", lineno + 1, fname);
  325. #endif /* LINEDIRECTIVE */
  326. }
  327. break;
  328. default:
  329. (void) fprintf(stderr, "%s: \"%s\", %d: Unexpected state\n",
  330. pname, fname, lineno);
  331. return 1;
  332. }
  333. }
  334. if (inprocess) {
  335. (void) fprintf(stderr, "%s: \"%s\", %d: Missing enddef\n",
  336. pname, fname, lineno);
  337. return 1;
  338. }
  339. if (fp != stdin)
  340. (void) fclose(fp);
  341. return 0;
  342. }