gnum4.c (95164) | gnum4.c (95887) |
---|---|
1/* $OpenBSD: gnum4.c,v 1.16 2002/02/16 21:27:48 millert Exp $ */ | 1/* $OpenBSD: gnum4.c,v 1.18 2002/04/26 16:15:16 espie Exp $ */ |
2 3/* 4 * Copyright (c) 1999 Marc Espie 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright --- 11 unchanged lines hidden (view full) --- 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28#include <sys/cdefs.h> | 2 3/* 4 * Copyright (c) 1999 Marc Espie 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright --- 11 unchanged lines hidden (view full) --- 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28#include <sys/cdefs.h> |
29__FBSDID("$FreeBSD: head/usr.bin/m4/gnum4.c 95164 2002-04-20 21:37:26Z jmallett $"); | 29__FBSDID("$FreeBSD: head/usr.bin/m4/gnum4.c 95887 2002-05-01 21:37:29Z jmallett $"); |
30 31/* 32 * functions needed to support gnu-m4 extensions, including a fake freezing 33 */ 34 35#include <sys/param.h> 36#include <sys/types.h> 37#include <sys/wait.h> --- 27 unchanged lines hidden (view full) --- 65 struct path_entry *next; 66} *first, *last; 67 68static struct path_entry *new_path_entry(const char *); 69static void ensure_m4path(void); 70static struct input_file *dopath(struct input_file *, const char *); 71 72static struct path_entry * | 30 31/* 32 * functions needed to support gnu-m4 extensions, including a fake freezing 33 */ 34 35#include <sys/param.h> 36#include <sys/types.h> 37#include <sys/wait.h> --- 27 unchanged lines hidden (view full) --- 65 struct path_entry *next; 66} *first, *last; 67 68static struct path_entry *new_path_entry(const char *); 69static void ensure_m4path(void); 70static struct input_file *dopath(struct input_file *, const char *); 71 72static struct path_entry * |
73new_path_entry(dirname) 74 const char *dirname; | 73new_path_entry(const char *dirname) |
75{ 76 struct path_entry *n; 77 78 n = malloc(sizeof(struct path_entry)); 79 if (!n) 80 errx(1, "out of memory"); 81 n->name = strdup(dirname); 82 if (!n->name) 83 errx(1, "out of memory"); 84 n->next = 0; 85 return n; 86} 87 88void | 74{ 75 struct path_entry *n; 76 77 n = malloc(sizeof(struct path_entry)); 78 if (!n) 79 errx(1, "out of memory"); 80 n->name = strdup(dirname); 81 if (!n->name) 82 errx(1, "out of memory"); 83 n->next = 0; 84 return n; 85} 86 87void |
89addtoincludepath(dirname) 90 const char *dirname; | 88addtoincludepath(const char *dirname) |
91{ 92 struct path_entry *n; 93 94 n = new_path_entry(dirname); 95 96 if (last) { 97 last->next = n; 98 last = n; --- 23 unchanged lines hidden (view full) --- 122 for (sweep = envpath; 123 (path = strsep(&sweep, ":")) != NULL;) 124 addtoincludepath(path); 125 free(envpath); 126} 127 128static 129struct input_file * | 89{ 90 struct path_entry *n; 91 92 n = new_path_entry(dirname); 93 94 if (last) { 95 last->next = n; 96 last = n; --- 23 unchanged lines hidden (view full) --- 120 for (sweep = envpath; 121 (path = strsep(&sweep, ":")) != NULL;) 122 addtoincludepath(path); 123 free(envpath); 124} 125 126static 127struct input_file * |
130dopath(i, filename) 131 struct input_file *i; 132 const char *filename; | 128dopath(struct input_file *i, const char *filename) |
133{ 134 char path[MAXPATHLEN]; 135 struct path_entry *pe; 136 FILE *f; 137 138 for (pe = first; pe; pe = pe->next) { 139 snprintf(path, sizeof(path), "%s/%s", pe->name, filename); 140 if ((f = fopen(path, "r")) != 0) { 141 set_input(i, f, path); 142 return i; 143 } 144 } 145 return NULL; 146} 147 148struct input_file * | 129{ 130 char path[MAXPATHLEN]; 131 struct path_entry *pe; 132 FILE *f; 133 134 for (pe = first; pe; pe = pe->next) { 135 snprintf(path, sizeof(path), "%s/%s", pe->name, filename); 136 if ((f = fopen(path, "r")) != 0) { 137 set_input(i, f, path); 138 return i; 139 } 140 } 141 return NULL; 142} 143 144struct input_file * |
149fopen_trypath(i, filename) 150 struct input_file *i; 151 const char *filename; | 145fopen_trypath(struct input_file *i, const char *filename) |
152{ 153 FILE *f; 154 155 f = fopen(filename, "r"); 156 if (f != NULL) { 157 set_input(i, f, filename); 158 return i; 159 } 160 if (filename[0] == '/') 161 return NULL; 162 163 ensure_m4path(); 164 165 return dopath(i, filename); 166} 167 168void | 146{ 147 FILE *f; 148 149 f = fopen(filename, "r"); 150 if (f != NULL) { 151 set_input(i, f, filename); 152 return i; 153 } 154 if (filename[0] == '/') 155 return NULL; 156 157 ensure_m4path(); 158 159 return dopath(i, filename); 160} 161 162void |
169doindir(argv, argc) 170 const char *argv[]; 171 int argc; | 163doindir(const char *argv[], int argc) |
172{ 173 ndptr p; 174 175 p = lookup(argv[2]); 176 if (p == NULL) 177 errx(1, "undefined macro %s", argv[2]); 178 argv[1] = p->defn; 179 eval(argv+1, argc-1, p->type); 180} 181 182void | 164{ 165 ndptr p; 166 167 p = lookup(argv[2]); 168 if (p == NULL) 169 errx(1, "undefined macro %s", argv[2]); 170 argv[1] = p->defn; 171 eval(argv+1, argc-1, p->type); 172} 173 174void |
183dobuiltin(argv, argc) 184 const char *argv[]; 185 int argc; | 175dobuiltin(const char *argv[], int argc) |
186{ 187 int n; 188 argv[1] = NULL; 189 n = builtin_type(argv[2]); 190 if (n != -1) 191 eval(argv+1, argc-1, n); 192 else 193 errx(1, "unknown builtin %s", argv[2]); 194} 195 196 197/* We need some temporary buffer space, as pb pushes BACK and substitution 198 * proceeds forward... */ 199static char *buffer; 200static size_t bufsize = 0; 201static size_t current = 0; 202 203static void addchars(const char *, size_t); | 176{ 177 int n; 178 argv[1] = NULL; 179 n = builtin_type(argv[2]); 180 if (n != -1) 181 eval(argv+1, argc-1, n); 182 else 183 errx(1, "unknown builtin %s", argv[2]); 184} 185 186 187/* We need some temporary buffer space, as pb pushes BACK and substitution 188 * proceeds forward... */ 189static char *buffer; 190static size_t bufsize = 0; 191static size_t current = 0; 192 193static void addchars(const char *, size_t); |
204static void addchar(char); | 194static void addchar(int); |
205static char *twiddle(const char *); 206static char *getstring(void); 207static void exit_regerror(int, regex_t *); 208static void do_subst(const char *, regex_t *, const char *, regmatch_t *); 209static void do_regexpindex(const char *, regex_t *, regmatch_t *); 210static void do_regexp(const char *, regex_t *, const char *, regmatch_t *); 211static void add_sub(size_t, const char *, regex_t *, regmatch_t *); 212static void add_replace(const char *, regex_t *, const char *, regmatch_t *); 213#define addconstantstring(s) addchars((s), sizeof(s)-1) 214 215static void | 195static char *twiddle(const char *); 196static char *getstring(void); 197static void exit_regerror(int, regex_t *); 198static void do_subst(const char *, regex_t *, const char *, regmatch_t *); 199static void do_regexpindex(const char *, regex_t *, regmatch_t *); 200static void do_regexp(const char *, regex_t *, const char *, regmatch_t *); 201static void add_sub(size_t, const char *, regex_t *, regmatch_t *); 202static void add_replace(const char *, regex_t *, const char *, regmatch_t *); 203#define addconstantstring(s) addchars((s), sizeof(s)-1) 204 205static void |
216addchars(c, n) 217 const char *c; 218 size_t n; | 206addchars(const char *c, size_t n) |
219{ 220 if (n == 0) 221 return; 222 while (current + n > bufsize) { 223 if (bufsize == 0) 224 bufsize = 1024; 225 else 226 bufsize *= 2; 227 buffer = realloc(buffer, bufsize); 228 if (buffer == NULL) 229 errx(1, "out of memory"); 230 } 231 memcpy(buffer+current, c, n); 232 current += n; 233} 234 235static void | 207{ 208 if (n == 0) 209 return; 210 while (current + n > bufsize) { 211 if (bufsize == 0) 212 bufsize = 1024; 213 else 214 bufsize *= 2; 215 buffer = realloc(buffer, bufsize); 216 if (buffer == NULL) 217 errx(1, "out of memory"); 218 } 219 memcpy(buffer+current, c, n); 220 current += n; 221} 222 223static void |
236addchar(c) 237 char c; | 224addchar(int c) |
238{ 239 if (current +1 > bufsize) { 240 if (bufsize == 0) 241 bufsize = 1024; 242 else 243 bufsize *= 2; 244 buffer = realloc(buffer, bufsize); 245 if (buffer == NULL) --- 7 unchanged lines hidden (view full) --- 253{ 254 addchar('\0'); 255 current = 0; 256 return buffer; 257} 258 259 260static void | 225{ 226 if (current +1 > bufsize) { 227 if (bufsize == 0) 228 bufsize = 1024; 229 else 230 bufsize *= 2; 231 buffer = realloc(buffer, bufsize); 232 if (buffer == NULL) --- 7 unchanged lines hidden (view full) --- 240{ 241 addchar('\0'); 242 current = 0; 243 return buffer; 244} 245 246 247static void |
261exit_regerror(er, re) 262 int er; 263 regex_t *re; | 248exit_regerror(int er, regex_t *re) |
264{ 265 size_t errlen; 266 char *errbuf; 267 268 errlen = regerror(er, re, NULL, 0); 269 errbuf = xalloc(errlen); 270 regerror(er, re, errbuf, errlen); 271 errx(1, "regular expression error: %s", errbuf); 272} 273 274static void | 249{ 250 size_t errlen; 251 char *errbuf; 252 253 errlen = regerror(er, re, NULL, 0); 254 errbuf = xalloc(errlen); 255 regerror(er, re, errbuf, errlen); 256 errx(1, "regular expression error: %s", errbuf); 257} 258 259static void |
275add_sub(n, string, re, pm) 276 size_t n; 277 const char *string; 278 regex_t *re; 279 regmatch_t *pm; | 260add_sub(size_t n, const char *string, regex_t *re, regmatch_t *pm) |
280{ 281 if (n > re->re_nsub) 282 warnx("No subexpression %zu", n); 283 /* Subexpressions that did not match are 284 * not an error. */ 285 else if (pm[n].rm_so != -1 && 286 pm[n].rm_eo != -1) { 287 addchars(string + pm[n].rm_so, 288 pm[n].rm_eo - pm[n].rm_so); 289 } 290} 291 292/* Add replacement string to the output buffer, recognizing special 293 * constructs and replacing them with substrings of the original string. 294 */ 295static void | 261{ 262 if (n > re->re_nsub) 263 warnx("No subexpression %zu", n); 264 /* Subexpressions that did not match are 265 * not an error. */ 266 else if (pm[n].rm_so != -1 && 267 pm[n].rm_eo != -1) { 268 addchars(string + pm[n].rm_so, 269 pm[n].rm_eo - pm[n].rm_so); 270 } 271} 272 273/* Add replacement string to the output buffer, recognizing special 274 * constructs and replacing them with substrings of the original string. 275 */ 276static void |
296add_replace(string, re, replace, pm) 297 const char *string; 298 regex_t *re; 299 const char *replace; 300 regmatch_t *pm; | 277add_replace(const char *string, regex_t *re, const char *replace, regmatch_t *pm) |
301{ 302 const char *p; 303 304 for (p = replace; *p != '\0'; p++) { 305 if (*p == '&' && !mimic_gnu) { 306 add_sub(0, string, re, pm); 307 continue; 308 } --- 16 unchanged lines hidden (view full) --- 325 continue; 326 } 327 } 328 addchar(*p); 329 } 330} 331 332static void | 278{ 279 const char *p; 280 281 for (p = replace; *p != '\0'; p++) { 282 if (*p == '&' && !mimic_gnu) { 283 add_sub(0, string, re, pm); 284 continue; 285 } --- 16 unchanged lines hidden (view full) --- 302 continue; 303 } 304 } 305 addchar(*p); 306 } 307} 308 309static void |
333do_subst(string, re, replace, pm) 334 const char *string; 335 regex_t *re; 336 const char *replace; 337 regmatch_t *pm; | 310do_subst(const char *string, regex_t *re, const char *replace, regmatch_t *pm) |
338{ 339 int error; 340 int flags = 0; 341 const char *last_match = NULL; 342 343 while ((error = regexec(re, string, re->re_nsub+1, pm, flags)) == 0) { 344 if (pm[0].rm_eo != 0) { 345 if (string[pm[0].rm_eo-1] == '\n') --- 23 unchanged lines hidden (view full) --- 369 string += pm[0].rm_eo; 370 } 371 if (error != REG_NOMATCH) 372 exit_regerror(error, re); 373 pbstr(string); 374} 375 376static void | 311{ 312 int error; 313 int flags = 0; 314 const char *last_match = NULL; 315 316 while ((error = regexec(re, string, re->re_nsub+1, pm, flags)) == 0) { 317 if (pm[0].rm_eo != 0) { 318 if (string[pm[0].rm_eo-1] == '\n') --- 23 unchanged lines hidden (view full) --- 342 string += pm[0].rm_eo; 343 } 344 if (error != REG_NOMATCH) 345 exit_regerror(error, re); 346 pbstr(string); 347} 348 349static void |
377do_regexp(string, re, replace, pm) 378 const char *string; 379 regex_t *re; 380 const char *replace; 381 regmatch_t *pm; | 350do_regexp(const char *string, regex_t *re, const char *replace, regmatch_t *pm) |
382{ 383 int error; 384 385 switch(error = regexec(re, string, re->re_nsub+1, pm, 0)) { 386 case 0: 387 add_replace(string, re, replace, pm); 388 pbstr(getstring()); 389 break; 390 case REG_NOMATCH: 391 break; 392 default: 393 exit_regerror(error, re); 394 } 395} 396 397static void | 351{ 352 int error; 353 354 switch(error = regexec(re, string, re->re_nsub+1, pm, 0)) { 355 case 0: 356 add_replace(string, re, replace, pm); 357 pbstr(getstring()); 358 break; 359 case REG_NOMATCH: 360 break; 361 default: 362 exit_regerror(error, re); 363 } 364} 365 366static void |
398do_regexpindex(string, re, pm) 399 const char *string; 400 regex_t *re; 401 regmatch_t *pm; | 367do_regexpindex(const char *string, regex_t *re, regmatch_t *pm) |
402{ 403 int error; 404 405 switch(error = regexec(re, string, re->re_nsub+1, pm, 0)) { 406 case 0: 407 pbunsigned(pm[0].rm_so); 408 break; 409 case REG_NOMATCH: 410 pbnum(-1); 411 break; 412 default: 413 exit_regerror(error, re); 414 } 415} 416 417/* In Gnu m4 mode, parentheses for backmatch don't work like POSIX 1003.2 418 * says. So we twiddle with the regexp before passing it to regcomp. 419 */ 420static char * | 368{ 369 int error; 370 371 switch(error = regexec(re, string, re->re_nsub+1, pm, 0)) { 372 case 0: 373 pbunsigned(pm[0].rm_so); 374 break; 375 case REG_NOMATCH: 376 pbnum(-1); 377 break; 378 default: 379 exit_regerror(error, re); 380 } 381} 382 383/* In Gnu m4 mode, parentheses for backmatch don't work like POSIX 1003.2 384 * says. So we twiddle with the regexp before passing it to regcomp. 385 */ 386static char * |
421twiddle(p) 422 const char *p; | 387twiddle(const char *p) |
423{ 424 /* This could use strcspn for speed... */ 425 while (*p != '\0') { 426 if (*p == '\\') { 427 switch(p[1]) { 428 case '(': 429 case ')': 430 case '|': --- 28 unchanged lines hidden (view full) --- 459} 460 461/* patsubst(string, regexp, opt replacement) */ 462/* argv[2]: string 463 * argv[3]: regexp 464 * argv[4]: opt rep 465 */ 466void | 388{ 389 /* This could use strcspn for speed... */ 390 while (*p != '\0') { 391 if (*p == '\\') { 392 switch(p[1]) { 393 case '(': 394 case ')': 395 case '|': --- 28 unchanged lines hidden (view full) --- 424} 425 426/* patsubst(string, regexp, opt replacement) */ 427/* argv[2]: string 428 * argv[3]: regexp 429 * argv[4]: opt rep 430 */ 431void |
467dopatsubst(argv, argc) 468 const char *argv[]; 469 int argc; | 432dopatsubst(const char *argv[], int argc) |
470{ 471 int error; 472 regex_t re; 473 regmatch_t *pmatch; 474 475 if (argc <= 3) { 476 warnx("Too few arguments to patsubst"); 477 return; --- 7 unchanged lines hidden (view full) --- 485 do_subst(argv[2], &re, 486 argc != 4 && argv[4] != NULL ? argv[4] : "", pmatch); 487 pbstr(getstring()); 488 free(pmatch); 489 regfree(&re); 490} 491 492void | 433{ 434 int error; 435 regex_t re; 436 regmatch_t *pmatch; 437 438 if (argc <= 3) { 439 warnx("Too few arguments to patsubst"); 440 return; --- 7 unchanged lines hidden (view full) --- 448 do_subst(argv[2], &re, 449 argc != 4 && argv[4] != NULL ? argv[4] : "", pmatch); 450 pbstr(getstring()); 451 free(pmatch); 452 regfree(&re); 453} 454 455void |
493doregexp(argv, argc) 494 const char *argv[]; 495 int argc; | 456doregexp(const char *argv[], int argc) |
496{ 497 int error; 498 regex_t re; 499 regmatch_t *pmatch; 500 501 if (argc <= 3) { 502 warnx("Too few arguments to regexp"); 503 return; --- 8 unchanged lines hidden (view full) --- 512 do_regexpindex(argv[2], &re, pmatch); 513 else 514 do_regexp(argv[2], &re, argv[4], pmatch); 515 free(pmatch); 516 regfree(&re); 517} 518 519void | 457{ 458 int error; 459 regex_t re; 460 regmatch_t *pmatch; 461 462 if (argc <= 3) { 463 warnx("Too few arguments to regexp"); 464 return; --- 8 unchanged lines hidden (view full) --- 473 do_regexpindex(argv[2], &re, pmatch); 474 else 475 do_regexp(argv[2], &re, argv[4], pmatch); 476 free(pmatch); 477 regfree(&re); 478} 479 480void |
520doesyscmd(cmd) 521 const char *cmd; | 481doesyscmd(const char *cmd) |
522{ 523 int p[2]; 524 pid_t pid, cpid; 525 int cc; 526 int status; 527 528 /* Follow gnu m4 documentation: first flush buffers. */ 529 fflush(NULL); --- 31 unchanged lines hidden --- | 482{ 483 int p[2]; 484 pid_t pid, cpid; 485 int cc; 486 int status; 487 488 /* Follow gnu m4 documentation: first flush buffers. */ 489 fflush(NULL); --- 31 unchanged lines hidden --- |