-int RredMethod::ed_rec(FILE *ed_cmds, FILE *in_file, FILE *out_file, int line,
- char *buffer, unsigned int bufsize, Hashes *hash) {
- int pos;
- int startline;
- int stopline;
- int mode;
- int written;
- char *idx;
-
- /* get the current command and parse it*/
- if (fgets(buffer, bufsize, ed_cmds) == NULL) {
- return line;
- }
- startline = strtol(buffer, &idx, 10);
- if (startline < line) {
- return ED_ORDERING;
- }
- if (*idx == ',') {
- idx++;
- stopline = strtol(idx, &idx, 10);
- }
- else {
- stopline = startline;
- }
- if (*idx == 'c') {
- mode = MODE_CHANGED;
- if (Debug == true) {
- std::clog << "changing from line " << startline
- << " to " << stopline << std::endl;
- }
- }
- else if (*idx == 'a') {
- mode = MODE_ADDED;
- if (Debug == true) {
- std::clog << "adding after line " << startline << std::endl;
- }
- }
- else if (*idx == 'd') {
- mode = MODE_DELETED;
- if (Debug == true) {
- std::clog << "deleting from line " << startline
- << " to " << stopline << std::endl;
- }
- }
- else {
- return ED_PARSER;
- }
- /* get the current position */
- pos = ftell(ed_cmds);
- /* if this is add or change then go to the next full stop */
- if ((mode == MODE_CHANGED) || (mode == MODE_ADDED)) {
- do {
- fgets(buffer, bufsize, ed_cmds);
- while ((strlen(buffer) == (bufsize - 1))
- && (buffer[bufsize - 2] != '\n')) {
- fgets(buffer, bufsize, ed_cmds);
- buffer[0] = ' ';
- }
- } while (strncmp(buffer, ".", 1) != 0);
- }
- /* do the recursive call */
- line = ed_rec(ed_cmds, in_file, out_file, line, buffer, bufsize,
- hash);
- /* pass on errors */
- if (line < 0) {
- return line;
- }
- /* apply our hunk */
- fseek(ed_cmds, pos, SEEK_SET);
- /* first wind to the current position */
- if (mode != MODE_ADDED) {
- startline -= 1;
- }
- while (line < startline) {
- fgets(buffer, bufsize, in_file);
- written = fwrite(buffer, 1, strlen(buffer), out_file);
- hash->Add((unsigned char*)buffer, written);
- while ((strlen(buffer) == (bufsize - 1))
- && (buffer[bufsize - 2] != '\n')) {
- fgets(buffer, bufsize, in_file);
- written = fwrite(buffer, 1, strlen(buffer), out_file);
- hash->Add((unsigned char*)buffer, written);
- }
- line++;
- }
- /* include from ed script */
- if ((mode == MODE_ADDED) || (mode == MODE_CHANGED)) {
- do {
- fgets(buffer, bufsize, ed_cmds);
- if (strncmp(buffer, ".", 1) != 0) {
- written = fwrite(buffer, 1, strlen(buffer), out_file);
- hash->Add((unsigned char*)buffer, written);
- while ((strlen(buffer) == (bufsize - 1))
- && (buffer[bufsize - 2] != '\n')) {
- fgets(buffer, bufsize, ed_cmds);
- written = fwrite(buffer, 1, strlen(buffer), out_file);
- hash->Add((unsigned char*)buffer, written);
- }
- }
- else {
- break;
- }
- } while (1);
- }
- /* ignore the corresponding number of lines from input */
- if ((mode == MODE_DELETED) || (mode == MODE_CHANGED)) {
- while (line < stopline) {
- fgets(buffer, bufsize, in_file);
- while ((strlen(buffer) == (bufsize - 1))
- && (buffer[bufsize - 2] != '\n')) {
- fgets(buffer, bufsize, in_file);
- }
- line++;
- }
- }
- return line;
-}
+ // parse in the effected linenumbers
+ char* idx;
+ errno=0;
+ unsigned long const startline = strtol(buffer, &idx, 10);
+ if (errno == ERANGE || errno == EINVAL) {
+ _error->Errno("rred", "startline is an invalid number");
+ return ED_PARSER;
+ }
+ if (startline > line) {
+ _error->Error("rred: The start line (%lu) of the next command is higher than the last line (%lu). This is not allowed.", startline, line);
+ return ED_ORDERING;
+ }
+ unsigned long stopline;
+ if (*idx == ',') {
+ idx++;
+ errno=0;
+ stopline = strtol(idx, &idx, 10);
+ if (errno == ERANGE || errno == EINVAL) {
+ _error->Errno("rred", "stopline is an invalid number");
+ return ED_PARSER;
+ }
+ }
+ else {
+ stopline = startline;
+ }
+ line = startline;
+
+ // which command to execute on this line(s)?
+ switch (*idx) {
+ case MODE_CHANGED:
+ if (Debug == true)
+ std::clog << "Change from line " << startline << " to " << stopline << std::endl;
+ break;
+ case MODE_ADDED:
+ if (Debug == true)
+ std::clog << "Insert after line " << startline << std::endl;
+ break;
+ case MODE_DELETED:
+ if (Debug == true)
+ std::clog << "Delete from line " << startline << " to " << stopline << std::endl;
+ break;
+ default:
+ _error->Error("rred: Unknown ed command '%c'. Abort.", *idx);
+ return ED_PARSER;
+ }
+ unsigned char mode = *idx;
+
+ // save the current position
+ unsigned const long pos = ftell(ed_cmds);
+
+ // if this is add or change then go to the next full stop
+ unsigned int data_length = 0;
+ if (mode == MODE_CHANGED || mode == MODE_ADDED) {
+ do {
+ ignoreLineInFile(ed_cmds, buffer);
+ data_length++;
+ }
+ while (strncmp(buffer, ".", 1) != 0);
+ data_length--; // the dot should not be copied
+ }
+
+ // do the recursive call - the last command is the one we need to execute at first
+ const State child = applyFile(ed_cmds, in_file, out_file, line, buffer, hash);
+ if (child != ED_OK) {
+ return child;
+ }
+
+ // change and delete are working on "line" - add is done after "line"
+ if (mode != MODE_ADDED)
+ line++;
+
+ // first wind to the current position and copy over all unchanged lines
+ if (line < startline) {
+ copyLinesFromFileToFile(in_file, out_file, (startline - line), hash, buffer);
+ line = startline;
+ }
+
+ if (mode != MODE_ADDED)
+ line--;
+
+ // include data from ed script
+ if (mode == MODE_CHANGED || mode == MODE_ADDED) {
+ fseek(ed_cmds, pos, SEEK_SET);
+ copyLinesFromFileToFile(ed_cmds, out_file, data_length, hash, buffer);
+ }