PageRenderTime 59ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/usr.bin/sed/main.c

https://bitbucket.org/gthummalapalle/minix-project2
C | 408 lines | 268 code | 32 blank | 108 comment | 62 complexity | b046828ec95352a25c9e7c7c56870844 MD5 | raw file
Possible License(s): AGPL-1.0, BSD-3-Clause, LGPL-2.0, WTFPL
  1. /* $NetBSD: main.c,v 1.21 2010/02/19 16:35:27 tnn Exp $ */
  2. /*-
  3. * Copyright (c) 1992, 1993
  4. * The Regents of the University of California. All rights reserved.
  5. *
  6. * This code is derived from software contributed to Berkeley by
  7. * Diomidis Spinellis of Imperial College, University of London.
  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. /*-
  34. * Copyright (c) 1992 Diomidis Spinellis.
  35. *
  36. * This code is derived from software contributed to Berkeley by
  37. * Diomidis Spinellis of Imperial College, University of London.
  38. *
  39. * Redistribution and use in source and binary forms, with or without
  40. * modification, are permitted provided that the following conditions
  41. * are met:
  42. * 1. Redistributions of source code must retain the above copyright
  43. * notice, this list of conditions and the following disclaimer.
  44. * 2. Redistributions in binary form must reproduce the above copyright
  45. * notice, this list of conditions and the following disclaimer in the
  46. * documentation and/or other materials provided with the distribution.
  47. * 3. All advertising materials mentioning features or use of this software
  48. * must display the following acknowledgement:
  49. * This product includes software developed by the University of
  50. * California, Berkeley and its contributors.
  51. * 4. Neither the name of the University nor the names of its contributors
  52. * may be used to endorse or promote products derived from this software
  53. * without specific prior written permission.
  54. *
  55. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  56. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  57. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  58. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  59. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  60. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  61. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  62. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  63. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  64. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  65. * SUCH DAMAGE.
  66. */
  67. #if HAVE_NBTOOL_CONFIG_H
  68. #include "nbtool_config.h"
  69. #endif
  70. #include <sys/cdefs.h>
  71. #ifndef lint
  72. __COPYRIGHT("@(#) Copyright (c) 1992, 1993\
  73. The Regents of the University of California. All rights reserved.");
  74. #endif /* not lint */
  75. #ifndef lint
  76. #if 0
  77. static char sccsid[] = "@(#)main.c 8.2 (Berkeley) 1/3/94";
  78. #else
  79. __RCSID("$NetBSD: main.c,v 1.21 2010/02/19 16:35:27 tnn Exp $");
  80. #endif
  81. #endif /* not lint */
  82. #include <sys/types.h>
  83. #include <ctype.h>
  84. #include <errno.h>
  85. #include <fcntl.h>
  86. #include <limits.h>
  87. #include <regex.h>
  88. #include <stddef.h>
  89. #include <stdio.h>
  90. #include <stdlib.h>
  91. #include <string.h>
  92. #include <unistd.h>
  93. #include "defs.h"
  94. #include "extern.h"
  95. /*
  96. * Linked list of units (strings and files) to be compiled
  97. */
  98. struct s_compunit {
  99. struct s_compunit *next;
  100. enum e_cut {CU_FILE, CU_STRING} type;
  101. char *s; /* Pointer to string or fname */
  102. };
  103. /*
  104. * Linked list pointer to compilation units and pointer to current
  105. * next pointer.
  106. */
  107. static struct s_compunit *script, **cu_nextp = &script;
  108. /*
  109. * Linked list of files to be processed
  110. */
  111. struct s_flist {
  112. char *fname;
  113. struct s_flist *next;
  114. };
  115. /*
  116. * Linked list pointer to files and pointer to current
  117. * next pointer.
  118. */
  119. static struct s_flist *files, **fl_nextp = &files;
  120. int aflag, eflag, nflag, ere;
  121. /*
  122. * Current file and line number; line numbers restart across compilation
  123. * units, but span across input files.
  124. */
  125. const char *fname; /* File name. */
  126. u_long linenum;
  127. int lastline; /* TRUE on the last line of the last file */
  128. static void add_compunit(enum e_cut, char *);
  129. static void add_file(char *);
  130. int main(int, char **);
  131. int
  132. main(int argc, char *argv[])
  133. {
  134. int c, fflag;
  135. setprogname(*argv);
  136. fflag = 0;
  137. while ((c = getopt(argc, argv, "ae:f:nrE")) != -1)
  138. switch (c) {
  139. case 'a':
  140. aflag = 1;
  141. break;
  142. case 'e':
  143. eflag = 1;
  144. add_compunit(CU_STRING, optarg);
  145. break;
  146. case 'f':
  147. fflag = 1;
  148. add_compunit(CU_FILE, optarg);
  149. break;
  150. case 'n':
  151. nflag = 1;
  152. break;
  153. case 'r':
  154. case 'E':
  155. ere = REG_EXTENDED;
  156. break;
  157. default:
  158. case '?':
  159. (void)fprintf(stderr,
  160. "usage:\t%s [-aEnr] script [file ...]\n\t%s [-aEnr] [-e script] ... [-f script_file] ... [file ...]\n",
  161. getprogname(), getprogname());
  162. exit(1);
  163. }
  164. argc -= optind;
  165. argv += optind;
  166. /* First usage case; script is the first arg */
  167. if (!eflag && !fflag && *argv) {
  168. add_compunit(CU_STRING, *argv);
  169. argv++;
  170. }
  171. compile();
  172. /* Continue with first and start second usage */
  173. if (*argv)
  174. for (; *argv; argv++)
  175. add_file(*argv);
  176. else
  177. add_file(NULL);
  178. process();
  179. cfclose(prog, NULL);
  180. if (fclose(stdout))
  181. err(FATAL, "stdout: %s", strerror(errno));
  182. exit (0);
  183. }
  184. /*
  185. * Like fgets, but go through the chain of compilation units chaining them
  186. * together. Empty strings and files are ignored.
  187. */
  188. char *
  189. cu_fgets(char **outbuf, size_t *outsize)
  190. {
  191. static enum {ST_EOF, ST_FILE, ST_STRING} state = ST_EOF;
  192. static FILE *f; /* Current open file */
  193. static char *s; /* Current pointer inside string */
  194. static char string_ident[30];
  195. size_t len;
  196. char *p;
  197. if (*outbuf == NULL)
  198. *outsize = 0;
  199. again:
  200. switch (state) {
  201. case ST_EOF:
  202. if (script == NULL)
  203. return (NULL);
  204. linenum = 0;
  205. switch (script->type) {
  206. case CU_FILE:
  207. if ((f = fopen(script->s, "r")) == NULL)
  208. err(FATAL,
  209. "%s: %s", script->s, strerror(errno));
  210. fname = script->s;
  211. state = ST_FILE;
  212. goto again;
  213. case CU_STRING:
  214. if ((snprintf(string_ident,
  215. sizeof(string_ident), "\"%s\"", script->s)) >=
  216. (int)(sizeof(string_ident) - 1))
  217. (void)strcpy(string_ident +
  218. sizeof(string_ident) - 6, " ...\"");
  219. fname = string_ident;
  220. s = script->s;
  221. state = ST_STRING;
  222. goto again;
  223. }
  224. case ST_FILE:
  225. if ((p = fgetln(f, &len)) != NULL) {
  226. linenum++;
  227. if (len >= *outsize) {
  228. free(*outbuf);
  229. *outsize = ROUNDLEN(len + 1);
  230. *outbuf = xmalloc(*outsize);
  231. }
  232. memcpy(*outbuf, p, len);
  233. (*outbuf)[len] = '\0';
  234. if (linenum == 1 && p[0] == '#' && p[1] == 'n')
  235. nflag = 1;
  236. return (*outbuf);
  237. }
  238. script = script->next;
  239. (void)fclose(f);
  240. state = ST_EOF;
  241. goto again;
  242. case ST_STRING:
  243. if (linenum == 0 && s[0] == '#' && s[1] == 'n')
  244. nflag = 1;
  245. p = *outbuf;
  246. len = *outsize;
  247. for (;;) {
  248. if (len <= 1) {
  249. *outbuf = xrealloc(*outbuf,
  250. *outsize + _POSIX2_LINE_MAX);
  251. p = *outbuf + *outsize - len;
  252. len += _POSIX2_LINE_MAX;
  253. *outsize += _POSIX2_LINE_MAX;
  254. }
  255. switch (*s) {
  256. case '\0':
  257. state = ST_EOF;
  258. if (s == script->s) {
  259. script = script->next;
  260. goto again;
  261. } else {
  262. script = script->next;
  263. *p = '\0';
  264. linenum++;
  265. return (*outbuf);
  266. }
  267. case '\n':
  268. *p++ = '\n';
  269. *p = '\0';
  270. s++;
  271. linenum++;
  272. return (*outbuf);
  273. default:
  274. *p++ = *s++;
  275. len--;
  276. }
  277. }
  278. }
  279. /* NOTREACHED */
  280. return (NULL);
  281. }
  282. /*
  283. * Like fgets, but go through the list of files chaining them together.
  284. * Set len to the length of the line.
  285. */
  286. int
  287. mf_fgets(SPACE *sp, enum e_spflag spflag)
  288. {
  289. static FILE *f; /* Current open file */
  290. size_t len;
  291. char *p;
  292. int c;
  293. if (f == NULL)
  294. /* Advance to first non-empty file */
  295. for (;;) {
  296. if (files == NULL) {
  297. lastline = 1;
  298. return (0);
  299. }
  300. if (files->fname == NULL) {
  301. f = stdin;
  302. fname = "stdin";
  303. } else {
  304. fname = files->fname;
  305. if ((f = fopen(fname, "r")) == NULL)
  306. err(FATAL, "%s: %s",
  307. fname, strerror(errno));
  308. }
  309. if ((c = getc(f)) != EOF) {
  310. (void)ungetc(c, f);
  311. break;
  312. }
  313. (void)fclose(f);
  314. files = files->next;
  315. }
  316. if (lastline) {
  317. sp->len = 0;
  318. return (0);
  319. }
  320. /*
  321. * Use fgetln so that we can handle essentially infinite input data.
  322. * Can't use the pointer into the stdio buffer as the process space
  323. * because the ungetc() can cause it to move.
  324. */
  325. p = fgetln(f, &len);
  326. if (ferror(f))
  327. err(FATAL, "%s: %s", fname, strerror(errno ? errno : EIO));
  328. cspace(sp, p, len, spflag);
  329. linenum++;
  330. /* Advance to next non-empty file */
  331. while ((c = getc(f)) == EOF) {
  332. (void)fclose(f);
  333. files = files->next;
  334. if (files == NULL) {
  335. lastline = 1;
  336. return (1);
  337. }
  338. if (files->fname == NULL) {
  339. f = stdin;
  340. fname = "stdin";
  341. } else {
  342. fname = files->fname;
  343. if ((f = fopen(fname, "r")) == NULL)
  344. err(FATAL, "%s: %s", fname, strerror(errno));
  345. }
  346. }
  347. (void)ungetc(c, f);
  348. return (1);
  349. }
  350. /*
  351. * Add a compilation unit to the linked list
  352. */
  353. static void
  354. add_compunit(enum e_cut type, char *s)
  355. {
  356. struct s_compunit *cu;
  357. cu = xmalloc(sizeof(struct s_compunit));
  358. cu->type = type;
  359. cu->s = s;
  360. cu->next = NULL;
  361. *cu_nextp = cu;
  362. cu_nextp = &cu->next;
  363. }
  364. /*
  365. * Add a file to the linked list
  366. */
  367. static void
  368. add_file(char *s)
  369. {
  370. struct s_flist *fp;
  371. fp = xmalloc(sizeof(struct s_flist));
  372. fp->next = NULL;
  373. *fl_nextp = fp;
  374. fp->fname = s;
  375. fl_nextp = &fp->next;
  376. }