/* Allocate and initialize an external filter. * @param chain the current chain or NULL for new chain * @param cmd the command to execute. * @param ... a NULL terminated list of (const char*) arguments to command, * not including argv[0]. * @return newest filter in chain */ struct filter *filter_create_ext (struct filter *chain, const char *cmd, ...) { struct filter *f; int max_args; const char *s; va_list ap; /* allocate and initialize new filter */ f = (struct filter *) flex_alloc (sizeof (struct filter)); if (!f) flexerror (_("flex_alloc failed (f) in filter_create_ext")); memset (f, 0, sizeof (*f)); f->filter_func = NULL; f->extra = NULL; f->next = NULL; f->argc = 0; if (chain != NULL) { /* append f to end of chain */ while (chain->next) chain = chain->next; chain->next = f; } /* allocate argv, and populate it with the argument list. */ max_args = 8; f->argv = (const char **) flex_alloc (sizeof (char *) * (max_args + 1)); if (!f->argv) flexerror (_("flex_alloc failed (f->argv) in filter_create_ext")); f->argv[f->argc++] = cmd; va_start (ap, cmd); while ((s = va_arg (ap, const char *)) != NULL) { if (f->argc >= max_args) { max_args += 8; f->argv = (const char **) flex_realloc (f->argv, sizeof (char *) * (max_args + 1)); } f->argv[f->argc++] = s; } f->argv[f->argc] = NULL; va_end (ap); return f; }
/* copy_string - returns a dynamically allocated copy of a string */ char * copy_string(const char *str) { const char *c1; char *c2; char *copy; size_t size; /* find length */ for (c1 = str; *c1; ++c1) { ; } size = (unsigned) (c1 - str + 1) * sizeof(char); copy = (char *) flex_alloc(size); if (copy == NULL) flexfatal(_("dynamic memory failure in copy_string()")); assert(copy != NULL); for (c2 = copy; (*c2++ = *str++) != 0;) { ; } return copy; }
/* Allocate and initialize an internal filter. * @param chain the current chain or NULL for new chain * @param filter_func The function that will perform the filtering. * filter_func should return 0 if successful, and -1 * if an error occurs -- or it can simply exit(). * @param extra optional user-defined data to pass to the filter. * @return newest filter in chain */ struct filter *filter_create_int (struct filter *chain, int (*filter_func) (struct filter *), void *extra) { struct filter *f; /* allocate and initialize new filter */ f = (struct filter *) flex_alloc (sizeof (struct filter)); memset (f, 0, sizeof (*f)); f->next = NULL; f->argc = 0; f->argv = NULL; f->filter_func = filter_func; f->extra = extra; if (chain != NULL) { /* append f to end of chain */ while (chain->next) chain = chain->next; chain->next = f; } return f; }
/* one-time initialization. Should be called before any sf_ functions. */ void sf_init (void) { assert(_sf_stk == NULL); _sf_stk = (scanflags_t*) flex_alloc ( sizeof(scanflags_t) * (_sf_max = 32)); if (!_sf_stk) lerr_fatal(_("Unable to allocate %zu of stack"), sizeof(scanflags_t)); _sf_stk[_sf_top_ix] = 0; }
/* The following is only needed when building flex's parser using certain * broken versions of bison. */ void *yy_flex_xmalloc(int size) { void *result = flex_alloc( (size_t) size ); if ( ! result ) flexfatal( _( "memory allocation failed in yy_flex_xmalloc()" ) ); return result; }
/** Append a line directive to the string buffer. * @param buf A string buffer. * @param filename file name * @param lineno line number * @return buf */ struct Buf *buf_linedir (struct Buf *buf, const char* filename, int lineno) { char *t, *fmt = "#line %d \"%s\"\n"; t = flex_alloc (strlen (fmt) + strlen (filename) + (int)(1 + log10(lineno>=0?lineno:-lineno)) + 1); sprintf (t, fmt, lineno, filename); buf = buf_strappend (buf, t); flex_free (t); return buf; }
/* Append a "%s" formatted string to a string buffer */ struct Buf *buf_prints (struct Buf *buf, const char *fmt, const char *s) { char *t; t = flex_alloc (strlen (fmt) + strlen (s) + 1); sprintf (t, fmt, s); buf = buf_strappend (buf, t); flex_free (t); return buf; }
void *allocate_array(int size, size_t element_size) { void *mem; size_t num_bytes = element_size * size; mem = flex_alloc( num_bytes ); if ( ! mem ) flexfatal( _( "memory allocation failed in allocate_array()" ) ); return mem; }
/* Append a "%s" formatted string to a string buffer */ struct Buf *buf_prints (struct Buf *buf, const char *fmt, const char *s) { char *t; size_t tsz; t = flex_alloc (tsz = strlen (fmt) + strlen (s) + 1); if (!t) flexfatal (_("Allocation of buffer to print string failed")); snprintf (t, tsz, fmt, s); buf = buf_strappend (buf, t); flex_free (t); return buf; }
/** Pushes "m4_undefine([[def]])m4_dnl" to end of buffer. * @param buf A buffer as a list of strings. * @param def The m4 symbol to undefine. * @return buf */ struct Buf *buf_m4_undefine (struct Buf *buf, const char* def) { const char * fmt = "m4_undefine( [[%s]])m4_dnl\n"; char * str; size_t strsz; str = (char*)flex_alloc(strsz = strlen(fmt) + strlen(def) + 2); if (!str) flexfatal (_("Allocation of buffer for m4 undef failed")); snprintf(str, strsz, fmt, def); buf_append(buf, &str, 1); return buf; }
/** Append a line directive to the string buffer. * @param buf A string buffer. * @param filename file name * @param lineno line number * @return buf */ struct Buf *buf_linedir (struct Buf *buf, const char* filename, int lineno) { char *dst, *src, *t; char *dupe; dupe = flex_alloc (strlen(filename) + 1); strncpy(dupe, filename, strlen(filename)); t = flex_alloc (strlen ("#line \"\"\n") + /* constant parts */ 2 * strlen (filename) + /* filename with possibly all backslashes escaped */ (int) (1 + log10 (abs (lineno))) + /* line number */ 1); /* NUL */ if (!t) flexfatal (_("Allocation of buffer for line directive failed")); for (dst = t + sprintf (t, "#line %d \"", lineno), src = dupe; *src; *dst++ = *src++) if (*src == '\\') /* escape backslashes */ *dst++ = '\\'; *dst++ = '"'; *dst++ = '\n'; *dst = '\0'; buf = buf_strappend (buf, t); flex_free (t); return buf; }
/** Compiles a regular expression or dies trying. * @param preg Same as for regcomp(). * @param regex Same as for regcomp(). * @param cflags Same as for regcomp(). */ void flex_regcomp(regex_t *preg, const char *regex, int cflags) { int err; memset (preg, 0, sizeof (regex_t)); if ((err = regcomp (preg, regex, cflags)) != 0) { const int errbuf_sz = 200; char *errbuf, *rxerr; errbuf = (char*)flex_alloc(errbuf_sz *sizeof(char)); if (!errbuf) flexfatal(_("Unable to allocate buffer to report regcomp")); rxerr = (char*)flex_alloc(errbuf_sz *sizeof(char)); if (!rxerr) flexfatal(_("Unable to allocate buffer for regerror")); regerror (err, preg, rxerr, errbuf_sz); snprintf (errbuf, errbuf_sz, "regcomp for \"%s\" failed: %s", regex, rxerr); flexfatal (errbuf); free(errbuf); free(rxerr); } }
/** Extract a copy of the match, or NULL if no match. * @param m A match as returned by regexec(). * @param src The source string that was passed to regexec(). * @return The allocated string. */ char *regmatch_dup (regmatch_t * m, const char *src) { char *str; int len; if (m == NULL || m->rm_so < 0) return NULL; len = m->rm_eo - m->rm_so; str = (char *) flex_alloc ((len + 1) * sizeof (char)); if (!str) flexfatal(_("Unable to allocate a copy of the match")); strncpy (str, src + m->rm_so, len); str[len] = 0; return str; }
static void sko_push(bool dc) { if(!sko_stack){ sko_sz = 1; sko_stack = (struct sko_state*)flex_alloc(sizeof(struct sko_state)*sko_sz); if (!sko_stack) flexfatal(_("allocation of sko_stack failed")); sko_len = 0; } if(sko_len >= sko_sz){ sko_sz *= 2; sko_stack = (struct sko_state*)flex_realloc(sko_stack,sizeof(struct sko_state)*sko_sz); } /* initialize to zero and push */ sko_stack[sko_len].dc = dc; sko_len++; }
int addsym(char *sym, char *str_def, int int_def, hash_table table, int table_size) { int hash_val = hashfunct( sym, table_size ); struct hash_entry *sym_entry = table[hash_val]; struct hash_entry *new_entry; struct hash_entry *successor; while ( sym_entry ) { if ( ! strcmp( sym, sym_entry->name ) ) { /* entry already exists */ return -1; } sym_entry = sym_entry->next; } /* create new entry */ new_entry = (struct hash_entry *) flex_alloc( sizeof( struct hash_entry ) ); if ( new_entry == NULL ) flexfatal( _( "symbol table memory allocation failed" ) ); if ( (successor = table[hash_val]) != NULL ) { new_entry->next = successor; successor->prev = new_entry; } else new_entry->next = NULL; new_entry->prev = NULL; new_entry->name = sym; new_entry->str_val = str_def; new_entry->int_val = int_def; table[hash_val] = new_entry; return 0; }
/** Splits the chain in order to write to a header file. * Similar in spirit to the 'tee' program. * The header file name is in extra. * @return 0 (zero) on success, and -1 on failure. */ int filter_tee_header (struct filter *chain) { /* This function reads from stdin and writes to both the C file and the * header file at the same time. */ const int readsz = 512; char *buf; int to_cfd = -1; FILE *to_c = NULL, *to_h = NULL; bool write_header; write_header = (chain->extra != NULL); /* Store a copy of the stdout pipe, which is already piped to C file * through the running chain. Then create a new pipe to the H file as * stdout, and fork the rest of the chain again. */ if ((to_cfd = dup (1)) == -1) flexfatal (_("dup(1) failed")); to_c = fdopen (to_cfd, "w"); if (write_header) { if (freopen ((char *) chain->extra, "w", stdout) == NULL) flexfatal (_("freopen(headerfilename) failed")); filter_apply_chain (chain->next); to_h = stdout; } /* Now to_c is a pipe to the C branch, and to_h is a pipe to the H branch. */ if (write_header) { fputs (check_4_gnu_m4, to_h); fputs ("m4_changecom`'m4_dnl\n", to_h); fputs ("m4_changequote`'m4_dnl\n", to_h); fputs ("m4_changequote([[,]])[[]]m4_dnl\n", to_h); fputs ("m4_define([[M4_YY_NOOP]])[[]]m4_dnl\n", to_h); fputs ("m4_define( [[M4_YY_IN_HEADER]],[[]])m4_dnl\n", to_h); fprintf (to_h, "#ifndef %sHEADER_H\n", prefix); fprintf (to_h, "#define %sHEADER_H 1\n", prefix); fprintf (to_h, "#define %sIN_HEADER 1\n\n", prefix); fprintf (to_h, "m4_define( [[M4_YY_OUTFILE_NAME]],[[%s]])m4_dnl\n", headerfilename ? headerfilename : "<stdout>"); } fputs (check_4_gnu_m4, to_c); fputs ("m4_changecom`'m4_dnl\n", to_c); fputs ("m4_changequote`'m4_dnl\n", to_c); fputs ("m4_changequote([[,]])[[]]m4_dnl\n", to_c); fputs ("m4_define([[M4_YY_NOOP]])[[]]m4_dnl\n", to_c); fprintf (to_c, "m4_define( [[M4_YY_OUTFILE_NAME]],[[%s]])m4_dnl\n", outfilename ? outfilename : "<stdout>"); buf = (char *) flex_alloc (readsz); if (!buf) flexerror (_("flex_alloc failed in filter_tee_header")); while (fgets (buf, readsz, stdin)) { fputs (buf, to_c); if (write_header) fputs (buf, to_h); } if (write_header) { fprintf (to_h, "\n"); /* write a fake line number. It will get fixed by the linedir filter. */ fprintf (to_h, "#line 4000 \"M4_YY_OUTFILE_NAME\"\n"); fprintf (to_h, "#undef %sIN_HEADER\n", prefix); fprintf (to_h, "#endif /* %sHEADER_H */\n", prefix); fputs ("m4_undefine( [[M4_YY_IN_HEADER]])m4_dnl\n", to_h); fflush (to_h); if (ferror (to_h)) lerr (_("error writing output file %s"), (char *) chain->extra); else if (fclose (to_h)) lerr (_("error closing output file %s"), (char *) chain->extra); } fflush (to_c); if (ferror (to_c)) lerr (_("error writing output file %s"), outfilename ? outfilename : "<stdout>"); else if (fclose (to_c)) lerr (_("error closing output file %s"), outfilename ? outfilename : "<stdout>"); while (wait (0) > 0) ; exit (0); return 0; }
/** Adjust the line numbers in the #line directives of the generated scanner. * After the m4 expansion, the line numbers are incorrect since the m4 macros * can add or remove lines. This only adjusts line numbers for generated code, * not user code. This also happens to be a good place to squeeze multiple * blank lines into a single blank line. */ int filter_fix_linedirs (struct filter *chain) { char *buf; const int readsz = 512; int lineno = 1; bool in_gen = true; /* in generated code */ bool last_was_blank = false; if (!chain) return 0; buf = (char *) flex_alloc (readsz); if (!buf) flexerror (_("flex_alloc failed in filter_fix_linedirs")); while (fgets (buf, readsz, stdin)) { regmatch_t m[10]; /* Check for #line directive. */ if (buf[0] == '#' && regexec (®ex_linedir, buf, 3, m, 0) == 0) { char *fname; /* extract the line number and filename */ fname = regmatch_dup (&m[2], buf); if (strcmp (fname, outfilename ? outfilename : "<stdout>") == 0 || strcmp (fname, headerfilename ? headerfilename : "<stdout>") == 0) { char *s1, *s2; char filename[MAXLINE]; s1 = fname; s2 = filename; while ((s2 - filename) < (MAXLINE - 1) && *s1) { /* Escape the backslash */ if (*s1 == '\\') *s2++ = '\\'; /* Escape the double quote */ if (*s1 == '\"') *s2++ = '\\'; /* Copy the character as usual */ *s2++ = *s1++; } *s2 = '\0'; /* Adjust the line directives. */ in_gen = true; snprintf (buf, readsz, "#line %d \"%s\"\n", lineno + 1, filename); } else { /* it's a #line directive for code we didn't write */ in_gen = false; } free (fname); last_was_blank = false; } /* squeeze blank lines from generated code */ else if (in_gen && regexec (®ex_blank_line, buf, 0, NULL, 0) == 0) { if (last_was_blank) continue; else last_was_blank = true; } else { /* it's a line of normal, non-empty code. */ last_was_blank = false; } fputs (buf, stdout); lineno++; } fflush (stdout); if (ferror (stdout)) lerr (_("error writing output file %s"), outfilename ? outfilename : "<stdout>"); else if (fclose (stdout)) lerr (_("error closing output file %s"), outfilename ? outfilename : "<stdout>"); return 0; }
/* 1,3,5,7: hard rotation */ static int rotate_hard(image_t *image, int angle) { osspriteop_area *area; osspriteop_header *header; osspriteop_area *newarea; osspriteop_header *newheader; int w,h; int neww,newh; size_t sprimgbytes; size_t sprrowbytes; int c0,c1,c2,c3; os_trfm t; osspriteop_trans_tab *trans_tab; int log2bpp; int xeig,yeig; area = (osspriteop_area *) image->image; header = sprite_select(area, 0); w = image->display.dims.bm.width; h = image->display.dims.bm.height; /* work out sprite area size */ read_mode_vars(header->mode, &xeig, &yeig, &log2bpp); neww = (h << yeig) >> xeig; newh = (w << xeig) >> yeig; sprrowbytes = (((neww << log2bpp) + 31) & ~31) >> 3; sprimgbytes = sizeof(osspriteop_area) + sizeof(osspriteop_header); sprimgbytes += sprrowbytes * newh; /* alloc area */ if (flex_alloc((flex_ptr) &newarea, sprimgbytes) == 0) goto NoMem; /* HEAP HAS MOVED! - update pointers */ area = (osspriteop_area *) image->image; header = sprite_select(area, 0); /* init area */ newarea->size = sprimgbytes; newarea->first = 16; osspriteop_clear_sprites(osspriteop_USER_AREA, newarea); /* create sprite */ /* this should be identical to the original, save for dimensions */ /* ### masks won't work yet */ osspriteop_create_sprite(osspriteop_NAME, newarea, header->name, 0, /* no palette */ /* ### */ neww, newh, header->mode); /* redirect to sprite */ newheader = sprite_select(newarea, 0); osspriteop_switch_output_to_sprite(osspriteop_PTR, newarea, (osspriteop_id) newheader, 0, &c0, &c1, &c2, &c3); /* set up drawing stuff */ if (sprite_colours((osspriteop_area **) &image->image, header, &trans_tab)) goto NoMem; /* problem: we're switched to a sprite which _may_ have moved now * so as a work-around, unswitch output and update pointers, then switch * back */ /* redirect back */ osspriteop_unswitch_output(c0, c1, c2, c3); /* HEAP HAS MOVED! - update pointers */ area = (osspriteop_area *) image->image; header = sprite_select(area, 0); /* redirect to sprite */ newheader = sprite_select(newarea, 0); osspriteop_switch_output_to_sprite(osspriteop_PTR, newarea, (osspriteop_id) newheader, 0, &c0, &c1, &c2, &c3); /* dimensions need to be in OS units now */ w <<= xeig; h <<= yeig; neww <<= xeig; /* these might be the wrong way around */ newh <<= yeig; /* set up our transform */ trfm_set_identity(&t); /* flip horizontally */ if (angle >= 4) { t.entries[0][0] = -t.entries[0][0]; t.entries[2][0] += w; } trfm_translate(&t, -w / 2, -h / 2); trfm_rotate_degs(&t, (angle & 3) * 90 * 65536); trfm_translate(&t, neww / 2, newh / 2); t.entries[0][0] *= 256; t.entries[0][1] *= 256; t.entries[1][0] *= 256; t.entries[1][1] *= 256; t.entries[2][0] *= 256; t.entries[2][1] *= 256; /* draw */ osspriteop_put_sprite_trfm(osspriteop_PTR, area, (osspriteop_id) header, 0, /* trfm_flags */ NULL, /* source_rect */ osspriteop_USE_MASK, /* action */ &t, trans_tab); /* redirect back */ osspriteop_unswitch_output(c0, c1, c2, c3); if (trans_tab) flex_free((flex_ptr) &trans_tab); /* replace previous sprite */ flex_free((flex_ptr) &image->image); image->display.dims.bm.width = neww >> xeig; /* see note above */ image->display.dims.bm.height = newh >> yeig; flex_reanchor((flex_ptr) &image->image, (flex_ptr) &newarea); image->display.file_size = sprimgbytes; return FALSE; /* success */ NoMem: oserror_report(0, "error.no.mem"); return TRUE; /* failure */ }
/** Adjust the line numbers in the #line directives of the generated scanner. * After the m4 expansion, the line numbers are incorrect since the m4 macros * can add or remove lines. This only adjusts line numbers for generated code, * not user code. This also happens to be a good place to squeeze multiple * blank lines into a single blank line. */ int filter_postprocess_output (struct filter *chain) { char *buf; const int readsz = 512; int lineno = 1; bool in_gen = true; /* in generated code */ bool last_was_blank = true; if (!chain) return 0; buf = (char *) flex_alloc (readsz); while (fgets (buf, readsz, stdin)) { char *p, *q; int is_blank = true; if (strncmp (buf, "#line ", 6) == 0) in_gen = false; if (strncmp (buf, "@output(", 8) == 0) { char *filename = strdup (buf); FILE *prev_stdout; /* Remove "@)\n". */ filename[strlen (filename) - 3] = '\0'; prev_stdout = freopen (filename + 8, "w+", stdout); if (prev_stdout == NULL) lerrsf (_("could not create %s"), filename + 8); free (filename); lineno = 1; outfile_created = 1; last_was_blank = true; continue; } for (p = q = buf; *p; ) { if (!isspace (*p)) is_blank = false; if (*p == '@') { if (p[1] == '@') *q++ = p[1], p += 2; else if (p[1] == '{') *q++ = '[', p += 2; else if (p[1] == '}') *q++ = ']', p += 2; else if (strncmp (p, "@oline@", 7) == 0) in_gen = true, q += sprintf (q, "%d", lineno + 1), p += 7; } else *q++ = *p++; } *q = '\0'; /* squeeze blank lines from generated code */ if (in_gen && is_blank && last_was_blank) continue; last_was_blank = is_blank; fputs (buf, stdout); lineno++; } fflush (stdout); if (ferror (stdout)) lerrsf (_("error writing output file %s"), outfilename ? outfilename : "<stdout>"); else if (fclose (stdout)) lerrsf (_("error closing output file %s"), outfilename ? outfilename : "<stdout>"); return 0; }